Java - Anfängerfrage zu Vererbung

yxy

Lieutenant
Registriert
Juli 2014
Beiträge
552
Hallo zusammen,

ich bräuchte eure Unterstützung.
Es wäre nett, wenn mir jemand von euch helfen würde.

Zu Thema:
Wir haben heute Vererbung bahandelt.
Dabei viel die Aussage: "private Methoden und Variablen werden nicht vererbt".
Diese Aussage habe ich z.B. auch auf dieser Seite gefunden:
https://de.wikibooks.org/wiki/Java_Standard:_Vererbung#private
Private-Elemente werden nicht vererbt.

Nun wollte ich diese Aussage an einem Code-Bsp. testen:
Code:
public class MainClass {
   
    public static void main(String[] args){
        Oberklasse OK1 = new Oberklasse();
        Unterklasse UK1 = new Unterklasse();
       
        OK1.changePriv(2);
        UK1.changePriv(5);
       
        OK1.print();
        UK1.print();
    }
}
//-----------------------------------------------
public class Oberklasse {
   
    private int priv;
   
    public void changePriv(int priv_){
        addOne(priv_);
    }
   
    private void addOne(int priv_){
        priv=priv_;
    }
   
    public void print(){
        System.out.println(priv);
    }
   
}
//-----------------------------------------
package Vererbung;

public class Unterklasse extends Oberklasse {
   
}

So wie ich das verstanden habe, dürfte ein Objekt der Unterklasse die Variable priv garnicht kennen. Denn diese ist ja privat d.h. sie wird nicht vererbt.
Auch die Methode addOne dürfte dem Objekt der Unterklasse unbekannt sein.
Dennoch funktioniert der Code.
Wo liegt mein Denkfehler?
 
Du liegst richtig bis zu der Aussage, dass die Überschriebene Klasse die Variable "priv" nicht kennt.

Um es allgemein zu formulieren: Unterklasse erben nur protected und public Variablen und Methoden.

Was dich verwirrt ist, dass du die vererbte public Methode "changePriv" auch auf der vererbten Klasse verwenden kannst. Du kannst nur addOne nicht direkt aufrufen, da diese private ist.
Das private nicht vererbt wird, heißt nicht das es nicht mehr da wäre. Du hast nur keinen direkten Zugriff von der Überschreibenden Klasse aus gesehen.

Du fragst dich jetzt sicher wozu das?

Private Variablen sollen nicht direkt von außen modifiziert werden. Dafür verwendet man public oder protected Methoden. Diese sind dann von außen sichtbar.
 
Deine changePriv Methode ist öffentlich / public, daher funktioniert das. Wenn du auf Unterklasse hingegen direkt addOne aufrufst, gibt es einen Compile-Fehler aus den von dir genannten Gründen.
 
Burfi schrieb:
Was dich verwirrt ist, dass du die vererbte public Methode "changePriv" auch auf der vererbten Klasse verwenden kannst.

Nicht ganz :).
Das mit den Methoden erkläre ich mir folgendermaßen:
Die public Methode "changePriv" wird vererbt d.h. man kann darauf auch aus dem Objekt der Unterklasse zugreifen. D.h. die Unterklasse kennt die Methode und kann sie in der Oberklasse aufrufen (was sie auch macht, sofern die Methode nicht in der Unterklasse überschrieben wurde). Die private Methode "addOne" wird nicht vererbt d.h. ich kann darauf nicht aus dem Objekt der Unterklasse zugreifen.
Man kann aber die Methode "addOne" aus der Methode "changePriv" aufrufen. Denn wenn man die Methode "changePriv" aus einem Objekt der Unterklasse aufruft, wird ja in den Code der Oberklasse gewechselt und damit befindet man sich nun auch innerhalb der Oberklasse. Daher ist nun die private (nur in der Oberklasse) sichtbare Methode "addOne" sichtbar und ich kann darauf zugreifen.
Exkurs: Wenn ich aber die geerbte Methode "changePriv" in der Unterklasse modifiziere (d.h. überschreibe) wechselt man nicht mehr in den Code der Oberklasse. D.h. nun kann die von der Unterklasse aufgerufenen Methode "changePriv" nicht mehr auf die Methode "addOne" zugreifen.
....Hoffe ihr könnt mir folgen und ich liege richtig.

Das Problem liegt beim private Member priv.
Dieser dürfte ja nicht an die Unterklasse vererbt werden.
Aber "UK1.print();" liefert mir eine Ausgabe d.h. der Member priv muss auch in der Unterklasse vorhanden sein.
Ich kann mir aber nicht erklären warum.
 
Der Denkfehler ist, dass du "nicht vererbt" mit "nicht vorhanden" gleichsetzt.
Die privaten Variablen und Methoden sind weiterhin vorhanden, dürfen aber nur in der Basis Klasse verwendet werden.
Wenn die Basis Klasse nun also mit einer public Methode auf ihre privaten Variablen/Methoden zugreift, so ist dies erlaubt.
 
Hm, so ganz klar ist mir das noch nicht.
Wie kann man sich das am Besten vorstellen?

Kann ich mir dann ein Objekt der Unterklasse so vorstellen, dass es aus einem Objekt der Oberklasse und einer möglichen "Erweiterung" besteht.
Dabei kann ich nur auf die Inhalte im enthaltenen Oberklassenobjekt zugreifen die vererbt wurden (d.h. nicht private sind). Duch eine vererbte Methode (z.B. public) kann ich in dieses innere Oberklassenobjekt kommen.

Hoffe das klingt jetzt nicht lächerlich :), aber ich kann doch dann verbildlichen:
Das Objekt der Unterklasse ist wie eine Mango aufgebaut. Der Kern ist dabei des enthaltene Oberklassenobjekt und die Hülle die "Erweiterung". In den Kern kann ich nur durch vererbte Methoden/Member blicken.
 
Der Vergleich hinkt etwas. Um auf die public-Methoden der Oberklasse/Kern zuzugreifen, müssten man demnach erst durch die Unterklasse/Fruchtfleisch kommen. Daher entspricht dieser Vergleich eher dem Verhältnis von der Oberklasse zu deren privaten priv-Variable, als nicht von außen erreichbarem Kern.
Besser: Spiegelei. Die Oberklasse ist das Dotter und teilweise von außen erreichbar, die Unterklasse erweitert sich um das Dotter herum.
 
Darlis schrieb:
Besser: Spiegelei. Die Oberklasse ist das Dotter. Die Unterklasse das Eiweiß um das Dotter herum. Das Dotter ist teilweise (alle nicht private Methoden/Member) vom Eiweiß aus erreichbar. Um jedoch auf die Mitte des Dotters (die privaten Methoden/Meber) zugreifen zu können, muss man zunächst in das Dotter gelangen (durch eine nicht private Methode).

D.h. wenn ich ein neues Objekt der Unterklasse erzeuge wird automatisch ein Spiegelei (Dotter+Eiweiß) erzeugt.
Alles was von der Oberklasse vererbt wird (=Rand des Dotters), kann ich direkt aus der Unterklasse (dem Eiweiß) verwenden (darauf zugreifen). Bei dem was nicht vererbt wird (=Mitte des Dotters), muss ich den Umweg über die Oberklasse machen (d.h. zunächst in das Dotter hineingehen).
 
Ähm, ich krieg das mit dem Spiegelei jetzt nicht in den Schädel :D Daher anders:

Es ist korrekt, dass ein Objekt einer Unterklasse eben auch immer ein Objekt der Oberklasse ist.

Du musst dir das ganze mehr mit dem Begriff "Sichtbarkeit" merken.

Wenn etwas nicht vererbt wird, dann ist es einfach nicht direkt sichtbar.

Bsp.:
Die Oberklasse hat eine private Variable a und eine Funktion, die public ist und auf a zugreift.
Dann kannst du bei einem Objekt der Vaterklasse auch direkt auf a zugreifen, ohne den Umweg über die Funktion zu gehen, den für das Objekt ist a sichtbar.
Wenn du in der Unterklasse bist, geht das nicht, da kann a nicht gesehen werden. Du hast aber die Funktion der Vaterklasse geerbt. Und da es eben eine Funktion der Vaterklasse ist und nicht der Unterklasse, ist a für diese Funktion wieder sichtbar. Du könntest allerdings mit keiner Funktion der Unterklasse auf a zugreifen.

Und jetzt brat ich mir'n Spiegelei in der Hoffnung, keinen Murks erzählt zu haben... :D
 
Um das mal bildlich darzustellen:
1527599741461.png


Du kannst aus der Unterklasse zwar changePriv und print sehen, nicht aber priv und addOne.
Aus der Oberklasse kannst du hingegen durchaus priv und addOne sehen, daher können auch die beiden öffentlichen Methoden der Oberklasse die privaten Eigenschaften/Methoden verändern.
 
Der Vergleich mit dem Spiegelei war hauptsächlich wegen dem Zugriff auf die Oberklasse von außen angedacht.

Anstatt mit "wird vererbt" und "wird nicht vererbt" zu denken, versuch es lieber mit der Sichtbarkeit wie Grimba angedeutet hat. D.h. die Unterklasse kann und hat alles was die Oberklasse auch kann und hat, durch den "private"-Modifikator hat diese aber eben nicht Zugriff auf alles. Die Vererbung ändert daran nichts! Interessant wird es erst mit dem "protected"-Modifikator.
 
Lasst mich mal zusammenfassen:

Wenn ich schreibe „public class Unterklasse extends Oberklasse“ so erzeuge ich eine Unterklasse, die alles enthält das auch in der Oberklasse steht (also auch die privaten Methoden und Member). Vererbt – und damit in der Unterklasse sichtbar – werden jedoch nur die nicht private Methoden und Member.
Wenn ich nun ein Objekt der Unterklasse erzeuge, so enthält es sowohl die Methoden & Member der Oberklasse, als auch die in der Unterklasse zusätzlich definierten Methoden & Member.
Auf nicht vererbte Methoden & Member kann ich aber aus dem Unterklassenobjekt nicht zugreifen. Mir bleibt also nur die Möglichkeit nichtvererbte Member (private Member der Oberklasse) über vererbte Methoden (nicht private Methoden der Oberklasse) einzusehen bzw. abzuändern. Auch auf nichtvererbte Methoden (private Methoden der Oberklasse) kann ich nur über vererbte Methoden (nicht private Methoden der Oberklasse) zugreifen.

Gibt es Verbesserungen bzw. Ergänzungen? :)
1527614490485.png
 
Alles richtig, bis auf die Grafik. Das Wort "nicht" steht aber auf der falschen Seite.
 
Schon besser. Der schon angedeutete Modifikator "protected" gehört ja auch zu den "nicht privaten", d.h. die Formulierung ist tatsächlich passender.
 
Ok, alles klar.
Dann Danke für eure Unterstützung!
 
Zurück
Oben