Das "I"-Prefix bei Interfaces



  • lolz schrieb:

    Dein Interface/rein virtuelle Klasse/was auch immer mit dem Namen A ist doch nur so lange "leicht" wie du es so lässt. Aber was machst du jetzt mit der Implementierung?

    Welche Implementierung??? Es ist ein Iterface! Nichts mit Implementierung. Kannst Du dir nicht vorstellen, das A einfach _so_ bleibt, wie es da steht? 😮 🙄

    Wenn dann macht jemand andere sowas:

    // Header von Interface A.
    class A
    {
    public:
       virtual void foo() = 0;
    };
    

    Der bleibt unangetastet.
    Will ich A implementieren, mach ich das:

    // Header von DefaultA, einer Interface-Impl. von A.
    
    #include "A.hpp"
    
    class DefaultA : public A
    {
      public:
         void foo()
         {
              //irgendwas...
         }
    };
    

    Und? A ist immer noch ein Interface. Da wird nichts dran gedreht. Und jemand anderes macht das, wenn er mit A arbeiten will:

    #include <A.hpp>
    
    // keine Abhängigkeit zum komplexen DefaultA!!!
    // Nur Interface A wird benutzt.
    
    class X
    {
      public:
          // Parameter: Interface A
          void bar( A &a )
          {
              a.foo(); // foo vom Interface A
          }
    };
    

    Natürlich muß irgendwo im Projekt irgendwie mal DefaultA instaziert werden - klar. Aber ich kann immer A benutzen. Das ist in jeder OO-Sprache so.

    So schwer vorzustellen, das obwohl es nicht interface A {}; sondern class A {}; heißt, nicht implementiert werden muß? "Namen sind Schall und Rauch!". Genau das gleich mit class und interface. Der Effekt ist entscheidend.



  • Artchi, ich glaub wir haben gerade aneinander vorbei geredet. Ich sprach von einer Interface Klasse für eine konkrete Klasse. Z.B. IList für die Klasse List.



  • Versteh trotzdem nicht was du sagen willst.



  • Artchi schrieb:

    lolz schrieb:

    Dein Interface/rein virtuelle Klasse/was auch immer mit dem Namen A ist doch nur so lange "leicht" wie du es so lässt. Aber was machst du jetzt mit der Implementierung?

    Welche Implementierung??? Es ist ein Iterface! Nichts mit Implementierung. Kannst Du dir nicht vorstellen, das A einfach _so_ bleibt, wie es da steht? 😮 🙄

    Wenn dann macht jemand andere sowas:

    // Header von Interface A.
    class A
    {
    public:
       virtual void foo() = 0;
    };
    

    Der bleibt unangetastet.
    Will ich A implementieren, mach ich das:

    // Header von DefaultA, einer Interface-Impl. von A.
    
    #include "A.hpp"
    
    class DefaultA : public A
    {
      public:
         void foo()
         {
              //irgendwas...
         }
    };
    

    Und? A ist immer noch ein Interface. Da wird nichts dran gedreht. Und jemand anderes macht das, wenn er mit A arbeiten will:

    #include <A.hpp>
    
    // keine Abhängigkeit zum komplexen DefaultA!!!
    // Nur Interface A wird benutzt.
    
    class X
    {
      public:
          // Parameter: Interface A
          void bar( A &a )
          {
              a.foo(); // foo vom Interface A
          }
    };
    

    Natürlich muß irgendwo im Projekt irgendwie mal DefaultA instaziert werden - klar. Aber ich kann immer A benutzen. Das ist in jeder OO-Sprache so.

    So schwer vorzustellen, das obwohl es nicht interface A {}; sondern class A {}; heißt, nicht implementiert werden muß? "Namen sind Schall und Rauch!". Genau das gleich mit class und interface. Der Effekt ist entscheidend.

    public interface A {
        public void foo();
        private B b = new B();
    }
    
    class A {
        public:
            A() {
                b = new B;
            }
    
            virtual void foo() = 0;
    
        private:
            B* b;
    };
    


  • lolz schrieb:

    Ich dachte man hätte sich im Thread darauf geeinigt, dass man in C++ das I davor schreibt damit man für die Implementierungsklasse den richtigen Namen benutzen kann. Also bei deinem Beispiel ein IA für die öffentliche Schnittstelle die leicht ist und keine abhängigkeiten hat und A welche die Implementierung beinhaltet.

    wer hat sich darauf geeinigt? bisher habe ich den anschein, dass es die meisten hier unsinnig finden. mir wäre lieber wenn man besser für implementierungsklassen ein präfix schreiben würde, als beim interface, weil man ja auf schnittstellen programmiert. oder noch besser: gar keine prefixe.



  • Also, wie man sich um ein I den Kopf zerbrechen kann, verstehe ich nicht. Es ist eine Konvention, an die man sich halten kann oder nicht. Ist genau das gleiche, wie wenn jemand sagt, er schreibt alle Methodennamen am Anfang groß. Und? Ich mache es nicht. Ich schreibe alles klein, selbst Klassennamen.

    Auf Arbeit aber schreiben wir die Interface, die in der Eclipse-Platform benutzt werden, am Anfang mit einem I. Warum? Weil jemand aus dem Team sich gerne an die Eclipse-Convention halten wollte. Naja, wurde dann halt so im Team beschlossen, und gut ist. Hätten aber auch alle sagen können "Nö, haben wir bisher auch nicht gemacht. Bin nicht dafür!".



  • Irgendwie verstehe ich nicht worauf der "unterschied ist ja .." hinaus will. Will er damit sagen, dass wenn man Attribute in Interfaces zulässt, sie das selbe sind wie Klassen? - Das will ja wohl keiner bestreiten.

    Aber sowas ist nunmal in einem Interface nicht erlaubt, aus einem gutem Grund,

    public interface A {
        public void foo();
        private B b = new B();
    }
    

    und das ist kein Interface mehr sondern eine abstrakte Klasse.

    class A {
        public:
            A() {
                b = new B;
            }
    
            virtual void foo() = 0;
    
        private:
            B* b;
    };
    

    Imho waren die Entwickler einfach zu faul sich Namen für Interfaces auszudenken, so habe sie einfach den Präfix I genommen. Man muss schon reichlich kreativ sein um für die Klasse Path ein Interface-Namen auszudenken. 😃



  • Was spricht eigentlich gegen? :

    //header
    class Path{
    public:
      void foo();
      // Methoden
    private:
      // Daten
    };
    
    // CPP Datei
    void Path::foo(){
      //...
    }
    

    oder wenn Kompilezeiten oder strikte Binärkompatibilität ein Thema sind dann:

    //header
    class Path{
    public:
      void foo();
      // Methoden
    private:
      struct Impl;
      Impl*m_impl;
    };
    
    // CPP Datei
    struct Path::Impl{
      //Daten
    };
    void Path::foo(){
      m_impl->...
    }
    


  • DEvent schrieb:

    Irgendwie verstehe ich nicht worauf der "unterschied ist ja .." hinaus will. Will er damit sagen, dass wenn man Attribute in Interfaces zulässt, sie das selbe sind wie Klassen? - Das will ja wohl keiner bestreiten.

    Aber sowas ist nunmal in einem Interface nicht erlaubt, aus einem gutem Grund,

    public interface A {
        public void foo();
        private B b = new B();
    }
    

    und das ist kein Interface mehr sondern eine abstrakte Klasse.

    class A {
        public:
            A() {
                b = new B;
            }
    
            virtual void foo() = 0;
    
        private:
            B* b;
    };
    

    Langsam komme ich mir echt veräppelt vor, wenn ich weiter argumentiere bzw. begründe. Das Problem beim zweiten Konstrukt ist ja, dass es nie ein Interface war sondern immer nur eine abstrakte Klasse, zwar hatte sie keine Felder, aber das allein macht es meiner Ansicht nach nicht zum Interface. Auch wenn man natürlich sinngemäß etwas ähnliches erreichen kann, ist es nicht dasselbe. Ich hoffe, dass ich auf dieses Thema nicht näher eingehen muss, denn sonst kommen wir vom Hundertsten ins Tausendste.

    Ben04 schrieb:

    Was spricht eigentlich gegen? :

    //header
    class Path{
    public:
      void foo();
      // Methoden
    private:
      // Daten
    };
    
    // CPP Datei
    void Path::foo(){
      //...
    }
    

    oder wenn Kompilezeiten oder strikte Binärkompatibilität ein Thema sind dann:

    //header
    class Path{
    public:
      void foo();
      // Methoden
    private:
      struct Impl;
      Impl*m_impl;
    };
    
    // CPP Datei
    struct Path::Impl{
      //Daten
    };
    void Path::foo(){
      m_impl->...
    }
    

    Mit dem Handle/Body Idiom löst du erstens nur ein C++ spezifisches Problem und sorgst dabei nur dafür, dass man die Member einer Klasse verändern kann, ohne gleich das ganze Projekt neu übersetzen zu müssen. Das sind Abhängigkeiten auf einer ganz anderen Ebene, die es so in anderen Sprachen überhaupt nicht gibt.

    Du kannst meinetwegen noch 5 Indirektionen einbauen, aber trotzdem wirst du transitive Abhängigkeiten nicht auflösen können. Um den ganzen theoretischen Erläuterungen einen praktischen Hintergrund zu geben: Erstelle ein neues Projekt und kopiere Path.hpp und Path.cpp in ein entsprechendes Include-Verzeichnis. Du wirst sehen, dass sich das Projekt nicht kompilieren lässt, weil vermutlich einige Header und Source Files fehlen, die Path.cpp includiert bzw., wenn man so will, referenziert. Diese ganze Prozedur wird sich wahrscheinlich wiederholen bis du letztendlich die gesamte Bibliothek einbinden musst und bitte tut mir den Gefallen und nervt mich jetzt nicht mit Fragen und Kommentaren ala "Ist mir doch egal ob ich die gesamte Bibliothek einbinde, dafür ist sie ja doch da.", denn darum geht es nicht. Dieses Beispiel sollte einfach nochmal auf einfache, nachvollziehbare Art klarstellen, dass Datenkapselung absolut nichts zur Abhängigkeitsauflösung beiträgt, aber das hatte ich eigentlich bereits erwähnt.

    Ich denke an dieser Stelle klinke ich mich, zugegebenermaßen bereits etwas gereizt, aus der Diskussion aus. Wer immer noch nicht nachvollziehen kann, was ich meine, soll sich selbst in einem guten Buch zu Objektorientierung schlau machen.



  • sdfsdf235sdf schrieb:

    Du kannst meinetwegen noch 5 Indirektionen einbauen, aber trotzdem wirst du transitive Abhängigkeiten nicht auflösen können.

    ein interface ist nichts anderes als eine art indirektion. und zu viel unnötige indirektion schadet mehr als es nutzt.

    zu den transitiven abhängigkeiten:

    |-----|          |-----|
    | A   | <--------| C   |      
    |-----|          |-----|
      / \
       |
       |
    |-----|
    | B   |
    |-----|
    

    C hängt von A ab. Da B eine spezialisierung von A ist, was formal gesehen nichts anders ist als "B teilmenge von A" ist somit C auch indirekt von B abhängig.

    BTW: wieso funktioniert latex nicht!? 😕



  • Langsam komme ich mir echt veräppelt vor, wenn ich weiter argumentiere bzw. begründe. Das Problem beim zweiten Konstrukt ist ja, dass es nie ein Interface war sondern immer nur eine abstrakte Klasse, zwar hatte sie keine Felder, aber das allein macht es meiner Ansicht nach nicht zum Interface. Auch wenn man natürlich sinngemäß etwas ähnliches erreichen kann, ist es nicht dasselbe. Ich hoffe, dass ich auf dieses Thema nicht näher eingehen muss, denn sonst kommen wir vom Hundertsten ins Tausendste.

    Ich glaub es ist jedem klar das man sich an die Regeln halten muss was ein Interface ausmacht, um ein Interface hinzuschreiben und keine abstrakte Klasse. Ein Interface hat nunmal keine Implementation sondern nur eine Definition der Schnittstelle. Wenn du dich daran hällst kannst du auch statt interface auch blablub schreiben, trotzdem bleibt es ein Interface.



  • mathik schrieb:

    sdfsdf235sdf schrieb:

    Du kannst meinetwegen noch 5 Indirektionen einbauen, aber trotzdem wirst du transitive Abhängigkeiten nicht auflösen können.

    ein interface ist nichts anderes als eine art indirektion. und zu viel unnötige indirektion schadet mehr als es nutzt.

    zu den transitiven abhängigkeiten:

    |-----|          |-----|
    | A   | <--------| C   |      
    |-----|          |-----|
      / \
       |
       |
    |-----|
    | B   |
    |-----|
    

    C hängt von A ab. Da B eine spezialisierung von A ist, was formal gesehen nichts anders ist als "B teilmenge von A" ist somit C auch indirekt von B abhängig.

    B, was imho mehr als A ist, ist Teilmenge von A 😕

    Entweder du hast dich da verschrieben, oder ich kann dir nicht folgen.



  • Klugscheiß0r schrieb:

    B, was imho mehr als A ist, ist Teilmenge von A 😕

    Entweder du hast dich da verschrieben, oder ich kann dir nicht folgen.

    nö. B ist nich mehr als A, sondern spezieller. A ist allgemeiner.
    Bsp.: die kategorie "Tiere" ist "größer" als die kategorie "Säugetiere".

    semantisch ist somit B eine teilmenge von A. Kannst dich ja mal mit der semantik von programmiersprachen befassen, dort wird sowas erläutert.


Anmelden zum Antworten