Interface- Klassen



  • PollerCPP schrieb:

    Was bringt mir so eine Interface- Klasse in C++?

    Es gibt keine echten Interface Klassen in C++. Man kann Klassen verwenden, dir nur ein Interface definieren, d.h. keinerlei Implementationsanteil haben. Interface Klassen sind eine Notlösung für nicht vorhandene Mehrfachvererbung.

    class Interface {
    public:
      virtual ~Interface() = 0;
      virtual foo () = 0;
    };
    
    class Basis {
    public:
      virtual ~Basis();
    ...
    };
    
    class Abgeleitet : public BasisKlasse, public Interface {
    ...
    };
    
    int main () {
      Abgeleitet a;
    
      Interface* p = dynamic_cast<Interface*>(&a);
      p->foo();
    }
    


  • Ahhh ja, verstanden,

    Vielen Dank,

    lg



  • soweit ich weiß, braucht man kein dynamic_cast für einen upcast, oder? es müsste auch so (implizit) gehen:

    Interface* p = &a;
    

    oder mit einer referenz:

    Interface &p = a;
    p.foo();
    


  • cast0r schrieb:

    soweit ich weiß, braucht man kein dynamic_cast für einen upcast, oder?

    Stimmt. Genaugenommen braucht man dafür garkeinen Cast (also auch keinen statischen oder umwandelnden).



  • Pardon zu schnell eingetippt, und nicht nachgedacht. 😞



  • PollerCPP schrieb:

    Ich hätte jetzt eine Frage zu den Interface- Klassen und zwar mache ich in Java ein Interface und leiten dan Klassen von diesem Interface ab,

    Nein, du erstellst Klassen die dieses Interface implementieren.

    ~john schrieb:

    Interface Klassen sind eine Notlösung für nicht vorhandene Mehrfachvererbung.

    Ein Interface ist eine Schnittstellendefinition. Du erbst ja nicht wirklich was vom Interface, sondern "unterschreibst einen Vertrag", dass deine Klasse diese Definition erfüllt.



  • sone schrieb:

    ~john schrieb:

    Interface Klassen sind eine Notlösung für nicht vorhandene Mehrfachvererbung.

    Ein Interface ist eine Schnittstellendefinition. Du erbst ja nicht wirklich was vom Interface, sondern "unterschreibst einen Vertrag", dass deine Klasse diese Definition erfüllt.

    Worauf john da hinauswollte, war der Grund, warum Java "interface" eingeführt hat 😉
    Mehrfachvererbung ist an und für sich eine feine Sache, allerdings auch reichlich kompliziert in der richtigen Anwendung (ich sag nur Diamond of Death). C++ Programmierer lernen (hoffentlich), damit verantwortungsbewußt umzugehen, Java Programmierer haben keine Mehrfachvererbung, damit fallen diese Probleme weg.
    Und um Situationen zu lösen, in denen Mehrfachvererbung wirklich etwas bringen würde, hat Java dann das Hilfskonstrukt "Interface". (in C++ nennt man sowas "abstrakte Klasse" - und die ist um einiges flexibler)



  • CStoll schrieb:

    C++ Programmierer lernen (hoffentlich), damit verantwortungsbewußt umzugehen, Java Programmierer haben keine Mehrfachvererbung, damit fallen diese Probleme weg.

    Das ist ja der Grund warum es nur die Schmalspurvariante gibt, dadurch braucht man keine Sprachmittel um Konflikte aufzulösen. Die Tatsache, daß es Interface Klassen gibt, ist das Eingeständnis, daß man nicht wirklich ohne Mehrfachvererbung auskommt. Aber selbst Interface Klassen sind nicht in jedem Fall frei von Konflikten.

    Und um Situationen zu lösen, in denen Mehrfachvererbung wirklich etwas bringen würde, hat Java dann das Hilfskonstrukt "Interface". (in C++ nennt man sowas "abstrakte Klasse" - und die ist um einiges flexibler)

    Eigentlich nicht, denn wenn man das ganze unter dem Blickwinkel von OOP alá Smalltalk betrachtet (dynamic vs. static Dispatching), dann sind Interface Klassen überflüssig. Nur sie erleichtern die Fehlersuche erheblich. In C++ ist es notwendig, Smalltalk kennt es nicht und Java hat es (wenn auch nur in abgespeckter Version), weil es das Debugging vereinfacht.



  • Es gibt keine echten Interface Klassen in C++.

    Aber sowas ähnliches. http://groups.google.ca/group/comp.std.c++/msg/85af30a61bf677e4?hl=en&lr=



  • ~john schrieb:

    ...In C++ ist es notwendig, Smalltalk kennt es nicht und Java hat es (wenn auch nur in abgespeckter Version), weil es das Debugging vereinfacht.

    😕
    sorry, das habe ich nicht verstanden. Was ist notwendig/unbekannt/vorhanden ?
    Abstrakte Klassen, Interface (wieso "braucht" C++ das), ... ?

    Gruß,

    Simon2.



  • ~john schrieb:

    Eigentlich nicht, denn wenn man das ganze unter dem Blickwinkel von OOP alá Smalltalk betrachtet (dynamic vs. static Dispatching), dann sind Interface Klassen überflüssig.

    Das ist eine Frage des Typkonzepts - wenn du die Typen völlig dynamisch zuordnen kannst, brauchst du nicht einmal Vererbung. Aber C++ und Java bauen auf einem eher statischen Typkonzept auf (der Compiler prüft bereits vor der Ausführung, ob die Typen zusammenpassen - ist imho günstiger, als erst zur Laufzeit auf die Probleme aufmerksam gemacht zu werden), da sind die Vererbungsbeziehungen notwendig.



  • .
    (hatte mist geschrieben, weil nicht ordentlich gelesen 🙂 )



  • Simon2 schrieb:

    ~john schrieb:

    ...In C++ ist es notwendig, Smalltalk kennt es nicht und Java hat es (wenn auch nur in abgespeckter Version), weil es das Debugging vereinfacht.

    😕
    sorry, das habe ich nicht verstanden. Was ist notwendig/unbekannt/vorhanden ?

    Ich bezog mich auf Mehrfachvererbung bzw. Interface Klassen.

    Smalltalk braucht so etwas nicht, weil es dynamic Dispatching gibt. Interfaces gibt es in Java nur für die Typsicherheit, über das Reflection Paket kann man es direkt wie in Smalltalk machen. C++ und Java nutzen für die Kontraktabsicherung Klassen/Interface Klassen. C++ braucht die Klassen auch für das static Dispatching.

    Beim dynamisches Dispatching wird erst zur Laufzeit des Programms nachgesehen, ob es eine Methode "void foo()" für das betreffende Objekt gibt. Wenn das der Fall ist wird die Methode ausgeführt. Dabei ist es vollkommen egal, ob die Klassen sich in einer Vererbungshierachie befinden oder nicht. Sollte die Methode nicht bekannt sein, wird die Nachricht entweder ignoriert oder eine Ausnahme geworfen. Das hängt davon ab, wie die Programmiersprache das handhabt.

    Beim statischen Dispatching wird schon zum Compile/Linkzeitpunkt festgelegt welche Methode welcher Methodenzeiger zugeordnet wird. Weil dem so ist, dann man nur Methoden aufrufen, die für den betreffenden Basiszeiger schon beim Compilezeitpunkt bekannt waren. Casting funktioniert ebenfalls nur für Objekte innerhalb der Vererbungshierachie.

    Ein kleines Pseudo-C++-Beispiel, was veraussetzt es gäbe dynamisc Dispatching in C++.

    class Object {
      Object();
      virtual Object () = 0;
    };
    
    class A : public Object {
      virtual void goo ();
    }
    
    class B : public Object {
      virtual void foo ();
    };
    
    int main () {
      A a;
      B* p = &a;
      p->foo(); // das geht in C++ nicht,
                // weil es kein dynamic Dispatching gibt
                // entsprechender Smalltalk Code liefe fehlerfrei
      Object* q = &a;
      q->foo();  // ditto
    }
    


  • Danke ~john für die ausführliche und erhellende Antwort,
    😋 👍 😋 👍 🕶

    Simon2.



  • @~john:
    mMn sieht das eher nach automatischer Objekt(-fragment)-Erzeugung aus. Es kann ja erst danach dynamisch dispatcht (und anschließend gebunden) werden (was auch in C++ mittels einer vtable geschieht). Aber vielleicht ist die Terminologie bei Smalltalk eine andere und fasst beides unter "dynamisches dispatching" zusammen.



  • Wenn ~john "dynamic dispatching" schreibt meint er (dynamisches) "duck typing". Beide Begriffe sind richtig, allerdsings hat mich "dynamic dispatching" auch erstmal ordentlich verwirrt.


Anmelden zum Antworten