Vererbung Hilfe zu Klassen / Vererbung

JavaFuzzi

Mitglied
Hallo,

ich habe hier eine Aufgabe bzgl. Vererbung von Klassen & suche zu dieser Hilfe.

(Quellcode siehe unten).


So habe ich das Programm analysiert:

Ein Objekt der Klasse D wird instanziiert.

Die oberste Elternklasse der Klasse D ist die Klasse A, diese beinhaltet eine Methode mit einer Textausgabe, aber diese erfolgt nicht, da die Methode privat ist.

Die Kindklasse von Klasse A ist Klasse B. Hier bin ich der Meinung, dass die Methode dieser Klasse ausgeführt werden müsste und die Textausgabe: BBBB erscheinen sollte. Warum passiert das nicht?

Die Kindklasse von B ist C, hier passiert garnichts.

Jetzt gehts in die unterste Kindklasse: D. Hier wird DDDD ausgegeben.


Laut Lösung & in der Praxis gibt das Programm aber nur DDDD aus. Warum wird BBBB nicht ausgegeben?
Wo liege ich falsch? :bloed:

In der Lösung steht schlicht: "DDDD" wird ausgegeben, eine Begründung / Erklärung gibt es nicht.

Ich bedanke mich bei euch für eine Erleuchtung :idea:


Hier das Programm:

Java:
public class A {
  private void tell() {
    System.out.println("AAAA");
  }
}

public class B extends A {
  public void tell() {
    System.out.println("BBBB");
  }
}

public class C extends B {
}

public class D extends C {
  private void tell() {
    System.out.println("DDDD");
  }
}


public class ABCD {
  public static void main (String[] args) {
    D d = new D();
    d.tell();
  }
}
 
Zuletzt bearbeitet:
es wird
Code:
"DDDD"
ausgegeben weil du auf einer Instanz der Klasse D .
Java:
tell();
aufrufst, keine ahnung was genau dein Problem da nun ist 🙂

würdest du nun eine der anderen Klassen instanzieren würde dann jeweils deren tell() methoden ausgeführt werden.

z.B

Java:
A a = new A();
a.tell();

// AAAA

würdest du nun folgendes machen , was möglich ist da B die Klasse A erweitert

Java:
A a = new B();
a.tell();

schaut die JVM immer erst in der subklasse nach ob dort eine Methode mit dem namen tell(); existiert, wenn ja wird diese ausgeführt , wenn nein dann schaut die JVM in der Superklasse und führt dann deren Methode aus.
 
Zuletzt bearbeitet:
Danke. Ich war verwirrt... Entschuldige.

Es wird ja eindeutig nur die Methode tell der Klasse D aufgerufen.

Und die Methode tell der Klasse D überschreibt die Methode tell von B, die bereits die von A überschrieben hat.

Das ist doch dann Polymorphie ?

(Ihr dürft lachen, wenn ich schwachsinn geschrieben habe 😉 )
 
Grundsätzlich solltst du dir erstmal angewöhnen das Überschreiben von Methoden über die annotation

Code:
@Override

kenntlich zu machen.

sonst kann es dir schnell mal passieren das du eine Methode die du ggf. nur überladen wolltest mal überschreibst ohne es zu merken.

und ja das ist Polymorphie.

Zumindest wenn du das hier machst

Java:
A a = new D();

a.tell();

der Variable a ist es egal welches Objekt du in ihr speicherst, solange es eine Subklasse der Klasse A ist, zudem ist es nun unrelevant auf welchem Objekt nun die methode tell(); ausgeführt wird solange diese mindestens in der Superklasse existiert, das wäre in diesem Fall die Klasse A, ansonsten die Klasse Objekt, von welcher alle Klassen abgeleitet werden ohne dies explizit anzugeben.


[TIPP]
Kleiner Spoiler :

da Java keine Mehrfachvererbung zulässt gibt es hier die Möglichkeit der Interface nutztung um diese Funktionalität anzubieten.

So kannst du z.B garantieren das der Code flexibel bleibt falls du später ggf. mal eine neue klasse hinzufügst, diese müsste dann nur das Interface erfülllen , also es implementieren um ebenfalls die funktionalität zu gewährleisten, dem Aufrufer ist dann vollkommen egal welche Klasse die Methode dann letzten endes ausführt.[/TIPP]
 
Zuletzt bearbeitet:
Und wenn:

Java:
D d = new D();
    d.tell();

ausgeführt wird, werden doch auch Methoden überschrieben? Ist doch auch Polymorphie?

Java:
@Override

Wo genau, wird das dann hingeschrieben?
 
Ja insofern dies eine abgeleitete Klasse ist und die Methode in der Basisklasse existiert / keine andere parameterliste enthält, und es wird an folgende stelle angefügt noch über dem Methodenkopf

Java:
@Override
public void tell(){...}

Wenn du eine abstrakte Basisklasse nutzt kannst du die Methoden in dieser auch abstrakt definieren um zu gewährleisten das die von Subklassen mit fuktionalität gefüllt werden müssen, somit zwingst du erbende klassen die Methode zu überschreiben, oder du implementierst die Methode in der Basisklasse leer, das nennt man dann Hook, so kannst du dann selbst festlegen ob du die Methode überschreiben willst oder nicht und diese in ihrer Basisversion einfach nur keine Funktionalität hat.
 
Zuletzt bearbeitet:
ok, also nur um sicherzugehen:

In meinem genannten Beispielprogramm, wenn folgendes ausgeführt wird:

Java:
    D d = new D();
        d.tell();


Wird die Methode tell der Klasse B von der Methode der Klasse D überschrieben und das ist dann Polymorphie?
 
Also folgendes, polymorphie kommt aus dem griechischen und bedeutet nichts anderes als vielseitig, dies bezieht sich auf das oben bereits erwähnte.

Mehr kann ich dir gleich sagen, da ich nun erstmal zur Arbeit fahren muss 🙂
 
Zuletzt bearbeitet:
So nun aber, war zu viel los sorry......

Hier nochmal ein kleines Beispiel, obwohl wir C nicht direkt von A ableiten können wir trotzdem die Methode tell() ausführen, dies liegt daran das wir von Klasse B ableiten welche die Methode ebenfalls überschreibt, in der Klasse C überschreiben wir diese Methode nun nicht, instanzieren wir nun ein Objekt der Klasse C und schauen mal was passiert :


Hier nochmal die Klassen im überblick, (ausnahmsweise der übersicht halber in einer Datei)

Java:
class A {
	
	public void tell(){
		System.out.println("AAAA");
	}
}

class B extends A {
	
	@Override
	public void tell(){
		System.out.println("BBBB");
	}
}

class C extends B{
	
}

class D extends C{
	
	@Override
	public void tell(){
		System.out.println("DDDD");
	}
}


Java:
public class Foo{

	public static void main(String[] args) {
	   
		A a = new C();
	    a.tell();
	    
	    /*
	     * Das hier ist das beste Beispiel der Polymorphie und auch der
	     * flexibilität
	     * 
	     * Wir haben eine Referenz auf die Superklasse A, dieser weisen 
	     * wir ein Objekt vom Typ C zu, in der Klasse C wird die Methode 
	     * tell() nicht überschrieben, nun sucht die JVM und der Compiler
	     * in der Klassenhierarchie aufwärts nach einer methode mit dem 
	     * Name tell() fündig wird sie hier in der Klasse B von der wir C 
	     * ableiten. somit führt dies zur Ausgabe 
	     * 
	     * "BBBB"
	     * 
	     */
    }
}
 
Zuletzt bearbeitet:
Java:
public class A {
  private void tell() {
    System.out.println("AAAA");
  }
}
 
public class B extends A {
  public void tell() {
    System.out.println("BBBB");
  }
}
 
public class C extends B {
}
 
public class D extends C {
  private void tell() {
    System.out.println("DDDD");
  }
}
Ich weiß nicht, ob es ein Tippfehler ist: Aber
Code:
D
kann
Code:
tell()
nicht private überschreiben, wenn eine höhere Klasse in der Hierarchie (
Code:
B
) die Methode bereits als public definiert hat. Von daher würde dein Code so gar nicht kompilieren.

Ansonsten: alle
Code:
tell()
-Implementierungen sind privat. Daher kann jede Klasse nur "seine" tell()-Methode kennen, da private Methoden aus Superklassen nicht von der erbenden Klasse gesehen werden können. Und folglich auch nur diese aufrufen. Das ist keine Polymorphie.

Wären alle tell()-Methoden "public", dann würde ich von Polymorphie sprechen, weil sich die gleiche Methode je nach Klasse eben anders verhält.
 
Also, ich sollte sowas nicht nach der Nachtschicht schreiben ^^

so sieht das ganze aus :

Java:
class A {
	
	public void tell(){
		System.out.println("AAAA");
	}
}

class B extends A {
	
	@Override
	public void tell(){
		System.out.println("BBBB");
	}
}

class C extends B{
	
}

class D extends C{
	
	@Override
	public void tell(){
		System.out.println("DDDD");
	}
}

Dieser Code ist anders als dein Beispiel, hier werden nur öffentliche Zugriffsmodifizierer verwendet !


So nun kommt der Haken, was dein Beispiel betrifft !

Wenn die Methoden wie ich in deinem Beispiel übersehen habe, tatsächlich als private deklariert sind, erhält auch nur die Klasse in welcher sich diese Methode befindet zugriff darauf!

Wie Natak richtig erkannt hat was ich verpennt habe kannst du keine Methoden von Superklassen überschreiben die nach außen hin nicht sichtbar sind, demnach kannst du bei den Methoden die eben einen Identischen Namen wie die in der Superklasse, auch keine Natation mit @Override aufführen da du diese Methoden ja nicht überschreibst, für den Programmfluss hat das folgende Auswirkungen :

Gehen wir mal von deinem Beispiel Code aus:

in der Klasse A ist die Methode tell(); als private deklariert, diese kann also auch nur innerhalb der Klasse aufgerufen werden :

Java:
class A {
	
	public A() {
	   tell();
    }
	
	private void tell(){
		System.out.println("AAAA");
	}
}

dies hier würde sich nicht kompilieren lassen , insofern sich die main Methode nicht innerhalb derselben klasse (Klasse A) befindet, da
Code:
tell();
nach außen hin nicht sichtbar ist !

Java:
public static void main(String[] args) {
	   A a = new A();
	   
	   a.tell();  // <--nicht sichtbar da als private makiert !
	   
	   /* Dies lässt sich nicht kompilieren */
    }

Daraus resultiert nun das du in der Klasse B, die Methode
Code:
tell();
zwar definierst, aber nicht die der Superklasse überschreibst ! Eine Notation mit @Override würde die IDE also schon im Vorfeld zurückweisen, und beim Versuch das ganze zu kompilieren würde ein Fehler auftreten.

Hier wäre es dann auch kein Fall von Polymorphie !

So nun zur Klasse D , in dieser definierst du die Methode tell(); als private, dies würde der Compiler aber nicht zulassen , da du hier versuchst eine gleichnamige Methode, mit identischer Parameterliste in ihrer Sichtbarkeit gegenüber der Basisklasse, in diesem Fall die Klasse B einzuschränken, dies ließe sich auch nicht Kompilieren

Code:
object -> A(private) -> B(public)-> C -> D(private)

Schau selbst :

Java:
public static void main(String[] args) {
		
		A a = new B();  // <<---Zulässig da Subklasse
		
		a.tell();  		// <--- nicht zulässig in A als private deklariert
		
		((B) a).tell(); // <--- zulässig da Explizieter Cast auf Subklasse
	   
    }

ich vermute mal dein Beispiel soll einfach nur darlegen wie sich die verschiedenen Sichtbarkeiten im Fall der Vererbung auf den Programmfluss auswirken oder ?
 
Zuletzt bearbeitet:
ich vermute mal dein Beispiel soll einfach nur darlegen wie sich die verschiedenen Sichtbarkeiten im Fall der Vererbung auf den Programmfluss auswirken oder ?

Ja, das auch und den Durchlauf der Vererbung und die Überschreibung der Methoden.

Ich habe die Aufgabe verstanden.

Danke.
 

Zurück
Oben