Abstrakte Klassen als Schnittstellen



  • roan312 schrieb:

    Hi, ich habe schon oft von Abstrakten Klassen als Schnittstellen gehört, wie funktioniert das?
    Ich vermute man Definiert eine A.Klasse in der Header Datei und einen Abkömling von ihr in der Implementierungs Datei.
    Danach kann man einfach per Polymorphie mit einen Pointer auf die A.Klasse arbeiten, ohne dass der "User" selbst Objekte der Schnittstelle instanzieren kann,
    liege ich da halbwegs richtig oder bin ich völlig auf dem Holzweg?

    Eine Schnittstelle definiert welche Methoden zur Verfügung gestellt werden müssen. Wie eine Schnittstelle implementiert ist interessiert den Verwender nicht, er wählt eine passende oder noch besser: Lässt sie erstellen (Factory).

    Beispiel: Team A muss auf Lib von Team B zugreifen, bereits am Anfang des Projktes muss die Schnittstelle geplant sein damit alles schön hinhaut. Nun wurde alles durchgeplant und die Schnittstelle steht, bloß hat Team B genausowenig wie Team A Code in dieser Zeit geschrieben. Also erstmal nur die Schnittstelle bauen:

    class Interface
    {
        virtual void foo () = 0;
        virtual void bar () = 0;
    };
    
    Interface* CreateInterface ();
    

    Team A benötigt macht also einstweilen nur folgendes:

    Interface* myInterface = CreateInterface();
    

    Damit das Alles auch debugbar wird erstellt Team B erstmal eine Dummy-Implementierung:

    class Dummy : public Interface
    {
        void foo () { cout << "FOO" << endl; }
        void bar () { cout << "BAR" << endl; }
    };
    
    Interface* CreateInterface ()
    {
        return new Dummy();
    }
    

    Sobald das beendet ist können beide Teams seelenruhig an ihrem Projekt arbeiten, soll nun die Dummy-Version durch eine neue ersetzt werden muss sich Team A drum nicht kümmern: B ändert einfach die Implementierung:

    Interface* CreateInterface ()
    {
        return new MostPowerfulInterfaceImpl();
    }
    

    Die Technik die für Schnittstellen in C++ verwendet wird sind Abstrakte Klassen + Polymorphismus. Die Idee dahinter bleibt aber in allen Sprachen: Implementierung von Schnittstelle trennen.

    MfG SideWinder



  • Wenn Du das weißt, hast Du die Antwort auf Deine Frage schon gewußt. Also war die Frage unsinnig.
    Eben durch ableiten einer abstrakten Klasse kannst Du die Form von konkreten Implementierungen festlegen. Also genau das was Schnittstellen auch tun.



  • Danke Sidewinder, aber noch zwei Fragen:
    Wieso soll die erbende Klasse in der Header-Datei stehen?
    Sie hat Team-B doch gar nicht zu interessieren.

    Und wozu braucht man dafür die A.Klasse?
    T.A. kann doch sofort die Schnittstelle der "fertigen" Klasse vorlegen
    und dann Stück für Stück die Implementierung erzeugen. (?)



  • frosty schrieb:

    Wenn Du das weißt, hast Du die Antwort auf Deine Frage schon gewußt. Also war die Frage unsinnig.
    Eben durch ableiten einer abstrakten Klasse kannst Du die Form von konkreten Implementierungen festlegen. Also genau das was Schnittstellen auch tun.

    War sie nicht, ich habe gefragt wie man sie am besten einsetzt, nicht wie man sie erstellt.



  • Als Tip:

    Wenn Du dich genauer informieren willst, dann wirf mal einen Blick in die "Bibel" der Software-Technik von Helmut Balzert.



  • roan312 schrieb:

    Hi, ich habe schon oft von Abstrakten Klassen als Schnittstellen gehört, wie funktioniert das?

    Da steht aber was anderes. 🙂



  • Stimmt, ich habe mich später aber noch präzisiert. 😃



  • ok, zusammenfassend:

    irgendwie Beide unpräzise.

    Vielleicht sollten wir beide das mal üben: Ich lesen; Du formulieren.

    😃 😃 😃

    Ciao, schönen Abend



  • Von mir aus... 🙂

    Aber um auf meine Frage zurück zu kommen:

    Und wozu braucht man dafür die A.Klasse?
    Team-A kann doch sofort die Schnittstelle der "fertigen" Klasse vorlegen
    und dann Stück für Stück die Implementierung erzeugen.



  • Interface wird von B bereitgestellt, die Dummy-Impl und die tolle Impl stammen beide von Team B und sind vorzugsweise in einer anderen Header-Datei gut aufgehoben (am besten alles rums in eine DLL). Team A hat noch gar keine Klasse in meinem Beispiel, alles was von denen stammt ist ihr Code um eine Schnittstelle zur Lib zu bekommen:

    Interface* teamA_kann_jetzt_lib_benutzen = CreateInterface();
    

    Oder hast du ganz einfach meine beiden Teams umgedreht, dann lautet die Antwort zu:

    Und wozu braucht man dafür die A.Klasse? 
    T.A. kann doch sofort die Schnittstelle der "fertigen" Klasse vorlegen 
    und dann Stück für Stück die Implementierung erzeugen. (?)
    

    A hat nun eine Dummy-Impl abgeschlossen die mehr schlecht als recht ist. Jetzt ist aber bar() auf das Ergebnis von foo() angewiesen or something like that, da kann ich nicht hergehen und die tolle Impl erst einmal nur in foo() reinschreiben weil bar() dann nicht mehr funktioniert und bar2() auch nicht und überhaupt dann alles erstmal kaputt ist.

    Außerdem kann ich so schön versionieren, per Parameter kann ich an CreateInterface vielleicht noch übergeben ob ich eine optimierende version will oder eine standard-version, weil die neue optimierende version nur auf den neuen rechnern läuft die kaum jemand hat. In jede Methode ne if-Abfrage welche version? ekelhaft

    Ja und dann gibts noch 100 weitere Vorteile die du dir alle reinziehen kansnt wenn du dir zB ein büchlein über COM kaufst, die haben das dort exzessiv benützt.

    MfG SideWinder



  • Vielen vielen Dank SideWinder, jetzt hab ich den Sinn der Sache verstanden.


Anmelden zum Antworten