Java Klassen und Veerbung mit nichtnachvollziebarer Methodenaufrufe :(

MrIP

Mitglied
Java:
public class Start {

public static void main(String[] args){

	Ober oo = new Ober();
	Ober ff = new Mitte();
	Unter uu = new Unter();
	
	oo.gg(ff);
	oo.gg(uu);
	ff.gg(ff);
	ff.gg(uu);
	uu.gg(ff);
	uu.gg(uu);

}
}

public class Ober {

	public void gg (Ober o){ System.out.println("A");}
	public void gg (Mitte m){System.out.println("B");}
	public void gg (Object m){System.out.println("O");}
}


public class Mitte extends Ober {
	public void gg (Ober o){ System.out.println("L");}
	public void gg (Unter u){System.out.println("M");}
}

public class Unter extends Mitte {

	public void gg (Ober o) {System.out.println("X");}
	public void gg (Mitte m){System.out.println("Z");}
	
}

Die Ausgabe ist:

A
B
L
B
X
M

Ich kann das nicht nachvollziehen. Kann mir jemand die Methodenaufruge detaliert erklären? Diese Aufgabe ist eine Klausuraufgabe und ich muss die Detailiert erklären. Ich komme nicht weiter, weil ich nicht weiß was JAVA hier macht.

Vielen Dank
 
Zunächst mal würde ich die Variablennamen oo, uu, ff und eventuell die Methode gg anständig umbenennen.
Danach ist das recht einfach:
Man muss sich nur noch anschauen an welchem Objekt wird die Methode gg mit welchem Objekt aufgerufen

Java:
Ober oo = new Ober();    //oo ist vom Typ Ober
Ober ff = new Mitte();   // ff ist nach aussen hin vom Typ Ober
        // benutzt aber die überschriebenen Methoden von Mitte
        // da über Mitte() instanziert (möglich da Mitte von Ober erbt)

oo.gg(ff); // an einem Objekt vom Typ Ober wird gg 
              // mit einem Objekt vom Typ Ober aufgerufen
              // --> System.out.println("A");

Das gemeine an dem ganzen ist das mit
Code:
Ober ff = new Mitte();
eine Superklasse über seine Subklasse instanziert wird.
 
Die Ausgabe

A (kann ich nachvollziehen)
B (kann ich nicht nachvollziehen da gg() überladene Methoden sind und ich in Ober keine gg() funktion mit dem Objekt - Unter (uu) sehen kann...wieso wird dann B ausgegeben?)

🙁
 
was sollte denn stattdessen ausgegeben werden? oder erwartest du eine Fehlermeldung 'Aufruf geht nicht'?
 
Aber ff.gg(uu); uu ist doch eine instanz von der Unterklasse und soweit ich das sehen kann, ist in ff eine methode gg(Unter uu) drin....wieso wird die nicht aufgerufen?
 
Achso Du redest vom zweiten B!
Du must bedenken, dass ff als Objekt von Typ Ober deklariert ist
und Ober besitzt keine Methode gg(Unter u)
Java:
Ober ff = new Mitte();
 
der Compiler legt schon zur Laufzeit fest, welche Methoden-Signatur aufgerufen wird, und zwar vom gegebenen Interface aus,
Compiler sieht Ober -> da passt gg(Mitte m) am besten

zur Laufzeit kann dann eine etwaige Subklasse höchstens noch genau die Methode gg(Mitte m) überschreiben und sich so einschleichen,
eine Methode mit anderer Signatur (anderen Parameter) hat keine Macht
 
Dann frage ich mich, wo der Unterschied zwischen

Java:
Ober ff = new Mitte();

und

Java:
Ober ff = new Ober();

ist?
 
das sieht man an Aufruf 1 und 3, einmal kommt A raus, einem L obwohl der Parameter (ff) und das Interface (Ober) gleich sind,
der Compiler wählt dieselbe Methoden-Signatur aus, aber bei Aufruf 3 ist es ein Mitte-Objekt, welches die Methode überschreibt
 
Das ist eigentlich genau das, was SlaterB erklärt hat.
In dem konkreten Fall bedeutet es, dass mit
Code:
Ober ff = new Mitte();
ein Objekt vom Typ Ober erzeugt wird, durch die initialisierung aber über Mitte() die Methode
Code:
gg(Ober o) {System.out.println("A");}
der Klasse Ober
durch die Methode
Code:
gg(Ober o) {System.out.println("L");}
der Klasse Mitte überschrieben wird.
Die Methode gg(Unter u) von Mitte wird nicht implementiert, da der Compiler ja von einem Ober Objekt ausgeht.

Man erzeugt hier quasi ein "kastriertes" Objekt vom Typ Mitte, welches keine Methode gg(Unter u) besitzt
 
Vielen dank...ich werde das erstmal so akzeptieren...meine Frage wäre, wo man so ein Mist programmiert?
Ist ja nur eine Klausuraufgabe :bahnhof:
 
Mich wundert, dass noch niemand den Fachbegriff genannt hat.

-> Dispatching

Ich hoffe, ich bekomme das auswendig von selbst hin:

Es gibt ein Formaltyp und ein Realtyp. X x = new Y();
X ist der Formaltyp von x und Y der Realtyp.

Für das Dispatching also der Auswahl einer Methode ist zunächst der Realtyp des Zielobjekts relevant, also Y. Enthält die Zielmethode nun Parameter wird anhand des Parameters NICHT anhand des Realtypen ausgewählt, sondern anhand des Formaltypen. Benötigt man dieses Double-Dispatching. bei der vom Realtypen auch bei Parametern entschieden werden soll, setzt man das Visitor-Pattern ein. Andere Programmiersprachen können Double-Dispatching ohne Entwurfsmuster. Java kann dies nicht ohne Entwurfsmuster.

Visitor pattern - Wikipedia, the free encyclopedia
 
Zuletzt bearbeitet:
Ja damit kann ich was anfangen...Ich glaub diese Form ist in C++ nicht ohne weiteres möglich wenn ich jetzt richtig überlege...vielen Dank
 

Zurück
Oben