Problem bei der Ausführungsreihenfolge

Neue Frage »

Auf diesen Beitrag antworten »
bamboozle Problem bei der Ausführungsreihenfolge

Hallo, ich habe gerade ein Denkproblem. Die Aufgabe ist folgende:

Geben Sie die Zeichenfolge an, die durch die Methode test erzeugt wird.
public class Oben {
public void gg (Oben o) { System.out.print("A "); }
public void gg (Mitte m) { System.out.print("B "); }
}
public class Mitte extends Oben {
public void gg (Oben o) { System.out.print("L "); }
public void gg (Unten u) { System.out.print("M "); }
}
public class Unten extends Mitte {
public void gg (Oben o) { System.out.print("X "); }
public void gg (Mitte m) { System.out.print("Z "); }
}
public class Prog {
public static void test() {
Oben oo = new Oben();
Oben ff = new Mitte();
Unten uu = new Unten();
oo.gg(ff);
oo.gg(uu);
ff.gg(ff);
ff.gg(uu);
uu.gg(ff);
uu.gg(uu);
}
}


Ich habe nun folgendes Problem. gg ist ja jeweils meine Methode in den einzelnen Klassen, immer abhängig von irgendeinem Eingabewert. Ich kann mir ja noch vorstellen: wenn ich gg(ff) habe, dann sucht der sich die passende Methode mit dem Parameter vom Typ Mitte und führt sie aus. Allerdings kriege ich gerade einen Hirnknoten wenn ich mir vorstelle, dass er diese Methode für ein Unter ausführt, also so: uu.gg(ff) ich verstehe dabei das "uu." nicht. Sagt mir das: "nehme Methode aus Klasse unter mit Parameter des Typs Mitte?"

Wenn das so richtig ist, dann frage ich mich wiederum für den Fall "uu.gg(uu)" was da passiert. Denn in der Klasse Unten gibt es keine Methode mit Parameter vom Typ Unten. Wird dann automatisch die Superklasse zu Rate gezogen, ob dort eine Methode mit diesem Paramter steht? oder passiert gar nichts? Und ebenso: was passiert bei oogg(uu) nimmt der dann die Subklasse?

Ich finde leider nirgendwo in meinem Buch oder in der Vorlesung die Erklärung dafür, ich wäre euch sehr dankbar wenn ihr mir das erklären könntet.

Liebe Grüße
 
Auf diesen Beitrag antworten »
ed209 RE: Problem bei der Ausführungsreihenfolge

Interessante Aufgabe smile

Zitat:

Ich habe nun folgendes Problem. gg ist ja jeweils meine Methode in den einzelnen Klassen, immer abhängig von irgendeinem Eingabewert. Ich kann mir ja noch vorstellen: wenn ich gg(ff) habe, dann sucht der sich die passende Methode mit dem Parameter vom Typ Mitte und führt sie aus.

Nein er sucht sich die passende Method die den Typ Oben bedient. Denn die Variable ff ist vom Typ Oben, entscheidend ist hier der Typ der Variable, nicht die Klasse der sie letztendlich angehoert.

Zitat:
Allerdings kriege ich gerade einen Hirnknoten wenn ich mir vorstelle, dass er diese Methode für ein Unter ausführt, also so: uu.gg(ff) ich verstehe dabei das "uu." nicht. Sagt mir das: "nehme Methode aus Klasse unter mit Parameter des Typs Mitte?"

Hier wird auf einem Objekt vom Typ Unten die Methode fuer einen Wert vom Typ Oben aufgerufen (ff ist vom Typ Oben).

Zitat:

Wenn das so richtig ist, dann frage ich mich wiederum für den Fall "uu.gg(uu)" was da passiert. Denn in der Klasse Unten gibt es keine Methode mit Parameter vom Typ Unten. Wird dann automatisch die Superklasse zu Rate gezogen, ob dort eine Methode mit diesem Paramter steht? oder passiert gar nichts?

Eine Klasse erbt automatisch die Methoden ihrer Oberklasse. Es sei denn eine eigene Methode hat dieselbe Signatur wie eine Methode der Oberklasse, dann wird diese Methode ueberrschrieben.
Es wird übrigens immer eine Methode ausgeführt; wenn es keine passende Methode gibt, dann wird ein Fehler beim compilieren ausgegeben.

Zitat:

Und ebenso: was passiert bei oogg(uu) nimmt der dann die Subklasse?

Klassen erben nie von ihren Unterklassen. In diesem Falle wird uu gecastet zum nächsthöheren Typen für den es eine Methode [i]gg[\i] gibt.

Zitat:

Ich finde leider nirgendwo in meinem Buch oder in der Vorlesung die Erklärung dafür, ich wäre euch sehr dankbar wenn ihr mir das erklären könntet.

Dieses Beispiel ist ja schon extrem knifflig. Für solche Fälle musst du im Zweifelsfall die Java Language Specification zu rate ziehen: http://java.sun.com/docs/books/jls/

Gruß,
ED209

PS: Sehr interessant ist übrigens daß bei ff.gg(uu); B herauskommt.
Auf diesen Beitrag antworten »
David_pb

Das Beispiel ist überhaupt nicht kniffelig. Der Compiler wählt immer die Methode mit dem besten 'Match' aus. Wenn es keine Methode gibt die genau zutrifft kann eine Methode gewählt werden die zutreffen würde wenn ein impliziter Cast möglich ist (z.B. oo.gg(uu) => B). Unabhängig davon ist es erlaubt Methoden zu überschreiben, was die Auswahl ggf nach oben verschiebt (Ableitungshierarchie).

Du musst also Unterscheiden zwischen Typ der Referenz (oder wie das in Java auch immer heißen mag) und Objekttyp. Beispiel:

oo.gg(ff); => A
oo.gg(uu); => B

Referenztyp und Objekttyp sind 'Oben'. Die Auswahl der möglichen Methoden beschränkt sich also auf das was die Klasse 'Oben' anbietet (es kann also auch nichts überschrieben werden usw...). Die Referenztypen von ff und uu sind 'Oben' (!) und 'Unten'. Für ff wird also gg(Oben) ausgewählt (passt ohne downcast) für uu gibts keinen passenden match, also wird gg(Mitte) gewählt.

ff.gg(ff); => L

Hier ist der Referenztyp von ff 'Oben' und der Objekttyp 'Mitte'. Da in 'Mitte' die Methode gg(Oben) überschrieben wurde wird diese gewählt, da perfekt zutreffend (nochmals: der Referenztyp von ff ist 'Oben').

ff.gg(uu); => B

Das ist gar nicht mal so interessant. Da ff den Referenztyp 'Oben' hat kann der Compiler nur von dort ausgehen (er findet gg(Unten) erst gar nicht). Würde Mitte z.B. gg(Mitte) überschreiben würde diese Methode gewählt werden...
 
Neue Frage »
Antworten »


Verwandte Themen