protected Member / protected Vererbung



  • 1. In einem anderen Thread wurde letztens gesagt, dass man Member so gut wie nie protected macht. Wieso nicht? Was ist böse daran?

    2. public Vererbung bedeutet ja "is-a" und private Vererbung "is implemented in terms of". Aber was bedeutet protected Vererbung? Gibt es überhaupt Situationen, in denen eine protected Vererbung Anwendung findet?

    Danke im Voraus.



    Man macht Member private, um sie zu Kapseln. Wenn man Variabeln nun protected sind, kann man in abgeleiteten Klassen troztdem direkt darauf zugreifen - damit ist die Kapselung etwas dahin. Von daher braucht man das eher selten. Natuerlich kann dieses Verhalten manchmal wuenschenswert sein - in den meisten Faellen jedoch nicht.

    Ich zitieren Scott Meyers aus "Effective C++"
    "[...]and protected inheritance is something whose meaning eludes me to this day". Will heissen, dass er bis heute nicht herausgefunden hat, wofuer man protected Vererbung brauchen kann. Daher wird man es wohl auch kaum brauchen.



  • Gugelmoser schrieb:

    1. In einem anderen Thread wurde letztens gesagt, dass man Member so gut wie nie protected macht. Wieso nicht? Was ist böse daran?

    Weil protected Membervariablen genauso wie public Membervariablen ungekapselte Implementierungsdetails sind.

    Gugelmoser schrieb:

    2. public Vererbung bedeutet ja "is-a" und private Vererbung "is implemented in terms of". Aber was bedeutet protected Vererbung? Gibt es überhaupt Situationen, in denen eine protected Vererbung Anwendung findet?

    Meiner Meinung nach bedeutet Vererbung immer "is a". public, protected oder private bestimmen nur wer von dieser "is a" Beziehung weiß.
    public Vererbung bedeutet dass jeder die Vererbungsrelation sieht, protected bedeutet dass nur abgeleitete Klassen die Relation sehen und private bedeutet dass nur die Klasse selbst die Ableitung sieht. Das bedeutet wiederung, dass bei public jeder einen Zeiger auf ein Objekt der Klasse in einen Basisklassenzeiger umwandeln kann, bei protected können das nur abgeleitete Klassen und bei private nur die Klasse selbst. protected Vererbung wird sehr selten mal sinnvoll sein, mir fällt im Moment kein Beispiel ein. Aber das heißt nicht dass es nie sinnvoll ist...



  • Gugelmoser schrieb:

    1. In einem anderen Thread wurde letztens gesagt, dass man Member so gut wie nie protected macht. Wieso nicht? Was ist böse daran?

    Bitte? Das macht man (zumindest ich) ziemlich oft, das ist doch die einzige Möglichkeit, Daten nach außen zu kapseln und trotzdem vererbbar zu machen!

    Natürlich sieht man sehr schwer einen Nutzen darin, wenn man eben nicht vererbbare Klassen erzeugen lassen will.



  • Hacker schrieb:

    Gugelmoser schrieb:

    1. In einem anderen Thread wurde letztens gesagt, dass man Member so gut wie nie protected macht. Wieso nicht? Was ist böse daran?

    Bitte? Das macht man (zumindest ich) ziemlich oft, das ist doch die einzige Möglichkeit, Daten nach außen zu kapseln und trotzdem vererbbar zu machen!

    Natürlich sieht man sehr schwer einen Nutzen darin, wenn man eben nicht vererbbare Klassen erzeugen lassen will.

    Wenn man das "ziemlich oft" macht, dann wohl weil man Vererbung nicht zur Modellierung von Abstraktion einsetzt, sondern für Code reuse missbraucht...


  • Mod

    Hacker schrieb:

    Bitte? Das macht man (zumindest ich) ziemlich oft, das ist doch die einzige Möglichkeit, Daten nach außen zu kapseln und trotzdem vererbbar zu machen!

    Weil du etwas ziemlich oft machst, ist das weder üblich noch guter Stil. Siehe zur Erklärung die Beiträge über deinem.



  • Wenn ich sie nicht als protected deklariere, dann können sie nur public sein (um sie vererbbar zu machen) (oder Setter/Getter haben, was aber IMHO unschön ist), was wiederum nicht im anfänglichen Sinne war. Also ist protected die Lösung. Oder bin ich etwa wieder doof 😕



  • Hacker schrieb:

    Wenn ich sie nicht als protected deklariere, dann können sie nur public sein (um sie vererbbar zu machen) (oder Setter/Getter haben, was aber IMHO unschön ist), was wiederum nicht im anfänglichen Sinne war. Also ist protected die Lösung. Oder bin ich etwa wieder doof 😕

    Das Problem ist nicht wie man die Member "vererbbar macht", sondern dass du sie überhaupt "vererbbar machen" willst...



  • Man könnte ein "Interface" für erbende Klassen basteln, z.B so:

    class Game {
        public:
            void update();
        protected:
            virtual void Init(GAMEMODE gm);
            virtual void AddObject(Object);
            virtual void RemoveObject(Object);
        private:
            Timer timer;
            std::vector<Objects> objects;
    };
    


  • dot schrieb:

    Hacker schrieb:

    Wenn ich sie nicht als protected deklariere, dann können sie nur public sein (um sie vererbbar zu machen) (oder Setter/Getter haben, was aber IMHO unschön ist), was wiederum nicht im anfänglichen Sinne war. Also ist protected die Lösung. Oder bin ich etwa wieder doof 😕

    Das Problem ist nicht wie man die Member "vererbbar macht", sondern dass du sie überhaupt "vererbbar machen" willst...

    Bitte!? Ist das jetzt unüblich geworden, VERERBUNG zu benutzen?



  • Hacker schrieb:

    dot schrieb:

    Hacker schrieb:

    Wenn ich sie nicht als protected deklariere, dann können sie nur public sein (um sie vererbbar zu machen) (oder Setter/Getter haben, was aber IMHO unschön ist), was wiederum nicht im anfänglichen Sinne war. Also ist protected die Lösung. Oder bin ich etwa wieder doof 😕

    Das Problem ist nicht wie man die Member "vererbbar macht", sondern dass du sie überhaupt "vererbbar machen" willst...

    Bitte!? Ist das jetzt unüblich geworden, VERERBUNG zu benutzen?

    Nein, wieso!?
    Aber normalerweise setzt man Vererbung zur Modellierung von abstrakten Konzepten ein und nicht um Daten zu vererben...zumindest heutzutage...zumindest in der OOP wie ich sie verstehe...



  • Also, ich vererbe fast immer auch Eigenschaften mit.



  • SeppJ schrieb:

    Hacker schrieb:

    Bitte? Das macht man (zumindest ich) ziemlich oft, das ist doch die einzige Möglichkeit, Daten nach außen zu kapseln und trotzdem vererbbar zu machen!

    Weil du etwas ziemlich oft machst, ist das weder üblich noch guter Stil. Siehe zur Erklärung die Beiträge über deinem.

    🙄



  • Hacker schrieb:

    Also, ich vererbe fast immer auch Eigenschaften mit.

    😕 Es ist doch gar nicht möglich, etwas nicht zu vereben. Jedes Objekt der Subklasse besitzt immerhin ein Objekt der Basisklasse. Nur weil auf etwas nicht zugegriffen werden kann, heißt das nicht, dass es nicht vererbt wurde.



  • Hacker schrieb:

    Wenn ich sie nicht als protected deklariere, dann können sie nur public sein (um sie vererbbar zu machen) (oder Setter/Getter haben, was aber IMHO unschön ist), was wiederum nicht im anfänglichen Sinne war. Also ist protected die Lösung. Oder bin ich etwa wieder doof 😕

    Es wird immer alles vererbt.

    Aber: alles was protected vererbt wird, hebt die Kapselung auf. idR wollen wir, dass gewisse Invarianten eingehalten werden. Wenn du nun protected Member hast, kann jede Kindklasse diese ändern ohne invarianten beachten zu müssen. Das ist schlecht.

    Eigentlich gibt es keinen Grund protected variablen zu haben. Und ich habe das noch nirgendwo sinnvoll eingesetzt gesehen geschweige denn selber mal gebraucht...

    PS: zeig mal ein kleines Beispiel her wo du protected variablen hast.



  • Gugelmoser schrieb:

    Hacker schrieb:

    Also, ich vererbe fast immer auch Eigenschaften mit.

    😕 Es ist doch gar nicht möglich, etwas nicht zu vereben. Jedes Objekt der Subklasse besitzt immerhin ein Objekt der Basisklasse. Nur weil auf etwas nicht zugegriffen werden kann, heißt das nicht, dass es nicht vererbt wurde.

    Das ist mir klar! Ich meine, ich mache sie protected, sodass ich auf sie zugreifen kann.


  • Mod

    Hacker schrieb:

    Das ist mir klar! Ich meine, ich mache sie protected, sodass ich auf sie zugreifen kann.

    Würdest du deine Kinder mit deinem Portemonnaie oder deinem Penis rumspielen lassen? Wenn sie was von dir wollen, sollen sie gefälligst fragen!



  • Gugelmoser schrieb:

    1. In einem anderen Thread wurde letztens gesagt, dass man Member so gut wie nie protected macht. Wieso nicht? Was ist böse daran?

    Da wollte ich dir heute noch antworten. Sorry, dass das so lange gedauert hat.

    Zuerst mal zum Unterschied von öffentlichen und privaten Membern: Es gibt Fanatiker, die behaupten, dass alle Member privat sein sollen und dass man wenn nötig öffentliche Getter und Setter bereitstellen soll. Bei vielen Membern macht das auch aus bekannten Gründen Sinn: Man verrät nichts über Implementierungsdetails, macht externen Code nicht von der Implementierung abhängig, Client-Code kann keine bösen Sachen mit meinen privaten Membern anfangen, ich kann den Datentyp ändern etc.

    Allerdings gibt es auch Member, auf die ich von außen uneingeschränkten Zugriff gewähren will. Klassisches Beispiel wäre std::pair. Wichtig bei öffentlichen Membern ist aber, dass sie sich nie bzgl. Datentyp, Bedeutung etc. ändern werden und ich nichts dagegen habe, dass Client-Code Dinge mit den Membern macht, an die ich ursprünglich nicht gedacht habe. Insbesondere darf es nicht möglich sein, dass ich durch externe Zugriffe auf meine öffentlichen Member in einen inkonsistenten Zustand gerate. Wenn ich also öffentliche Member habe, gebe ich Client-Code die Garantie, dass er mit den Membern machen kann, was er will, und dass sich dieser Teil meiner Implementierung nicht ändert.

    Was ist nun mit geschützten Membern? Für erbende Klassen verhalten sie sich wie öffentliche Member. Insbesondere können andere Programmierer (oder ich in einem Jahr, läuft aufs selbe hinaus) beliebig von meiner Klasse ableiten, sodass ich keine Kontrolle über die erbenden Member habe und Code, der auf meine geschützten Member zugreift, übers gesamte Projekt verstreut sein kann. Also muss ich den erbenden Klassen dieselben Garantien wie bei öffentlichen Membern geben. Für alle anderen sind geschützte Member wie private Member mit all ihren Nachteilen.

    Also vereinen geschützte Member die Nachteile öffentlicher und privater Member. Einerseits will ich die Member nicht privat haben (aus welchen Gründen auch immer, sonst bräuchte ich protected gar nicht), aber ich muss trotzdem Garantien geben wie bei öffentlichen Membern.

    Edit: Wenn du Member hast, für die du keine weitreichenden Garantien geben willst und auf die trotzdem nur die abgeleiteten Klassen Zugriff haben sollen, kannst du die Member privat und Getter und Setter protected machen.



  • Michael E. schrieb:

    Gugelmoser schrieb:

    1. In einem anderen Thread wurde letztens gesagt, dass man Member so gut wie nie protected macht. Wieso nicht? Was ist böse daran?

    Da wollte ich dir heute noch antworten. Sorry, dass das so lange gedauert hat.

    Kein Ding 😉

    Danke für eure Beiträge, insbesondere

    icarus2 schrieb:

    [...] and protected inheritance is something whose meaning eludes me to this day". Will heissen, dass er bis heute nicht herausgefunden hat, wofuer man protected Vererbung brauchen kann. Daher wird man es wohl auch kaum brauchen.

    und

    Michael E. schrieb:

    Was ist nun mit geschützten Membern? Für erbende Klassen verhalten sie sich wie öffentliche Member. Insbesondere können andere Programmierer (oder ich in einem Jahr, läuft aufs selbe hinaus) beliebig von meiner Klasse ableiten, sodass ich keine Kontrolle über die erbenden Member habe [...]

    dot schrieb:

    Meiner Meinung nach bedeutet Vererbung immer "is a". public, protected oder private bestimmen nur wer von dieser "is a" Beziehung weiß.

    Da bin ich anderer Meinung. Ich begründe mal kurz, wieso ich anderer Meinung bin:

    class Foo
    {
    	private:
    		int price;
    
    	public:
    		int getPrice() const { return price; }
    };
    
    class Bar : private Foo {};
    
    int main()
    {
    	Foo f;
    	f.getPrice();
    
    	Bar b;
    	b.getPrice(); // Error: 'int Foo::getPrice() const' is inaccessible.
    }
    

    Ich nehme "is-a" wörtlich. Und wenn ich mit Bar nicht genau dasselbe machen kann wie mit Foo, ist es kein "is-a" mehr.



  • Gugelmoser schrieb:

    dot schrieb:

    Meiner Meinung nach bedeutet Vererbung immer "is a". public, protected oder private bestimmen nur wer von dieser "is a" Beziehung weiß.

    Da bin ich anderer Meinung. Ich begründe mal kurz, wieso ich anderer Meinung bin:

    class Foo
    {
    	private:
    		int price;
    		
    	public:
    		int getPrice() const { return price; }
    };
    
    class Bar : private Foo {};
    
    int main()
    {
    	Foo f;
    	f.getPrice();
    	
    	Bar b;
    	b.getPrice(); // Error: 'int Foo::getPrice() const' is inaccessible.
    }
    

    Ich nehme "is-a" wörtlich. Und wenn ich mit Bar nicht genau dasselbe machen kann wie mit Foo, ist es kein "is-a" mehr.

    Da halt ich dagegen:

    class Foo
    {
    	private:
    		int price;
    
    	public:
    		int getPrice() const { return price; }
    };
    
    class Bar : private Foo
    {
    public:
      Foo& getFoo() { return *this; }
    };
    
    int main()
    {
    	Foo f;
    	f.getPrice();
    
    	Bar b;
    	b.getFoo().getPrice();
    }
    

    Wie gesagt, Bar ist ein Foo, nur weiß das eben niemand außer Bar 😉


Anmelden zum Antworten