Hallo,
ich lerne gerade Java und habe ein Verständnisproblem bei einer Aufgabe. Es soll entschieden werden, ob bestimmte Methodenaufrufe vom Compiler zugelassen werden und wenn ja, welche Ausgabe es gibt. Ich bin durch die Forensuche leider nicht schlauer geworden, deshalb hoffe ich, dass mir jemand helfen kann.
Es sind folgende Klassen gegeben:
Interface Inter{
public m(Hund h, Object o)
}
abstract class Super implements Inter{
public m(Lebewesen l1, Lebewesen l2)
}
class Sub extends Super{
public m(Hund h, Object o){
System.out.println("m1");
}
public m(Lebewesen l1, Lebewesen l2){
System.out.println("m2");
}
public m(Hund h, Tier t){
System.out.println("m3");
}
}
Außerdem:
class Lebewesen{}
class Tier extends Lebewesen{}
class Hund extends Tier{}
In der main-Methode werden jetzt folgende Objekte erzeugt:
Inter s1=new Sub();
Super s2=new Sub();
Hund h = new Hund();
Tier t = h;
Lebewesen l1=new Tier();
Lebewesen l2=new Tier();
Frage:
1. beim Aufruf s1.m(h,t); wird "m1" ausgegeben. Der Deklarationstyp von s1 ist Inter, deshalb kommen nur Methoden m() in Frage, die in Inter deklariert sind. Es wird jetzt die speziellste der passenden Methoden bzgl. der Parameter gesucht, hier gibt es nur eine und die Signatur passt. Diese wird dann aufgrund des Typen der Instanz, die s1 referenziert dynamisch an die überschriebene Methode in Sub gebunden. So habe ich das zumindest verstanden.
2. wieso erzeugt der Aufruf s2.m(h,t) dann einen Compilerfehler? Die Methode in Super passt auf den Aufruf, denn die Deklarationstypen der Übergebenen Parameter sind Subtypen der Parameter in der Methodensignatur. Diese müsste doch dann genau wie in 1. dynamisch in Sub gebunden werden (also "m2" ausgeben). Falls die Methode in Inter auch in Super als abstrakte Methode existiert (dabei bin ich mir nicht sicher), dann müsste diese gewählt werden, denn sie ist spezieller oder täusche ich mich?
Ein weiterer Aufruf wäre z.B. s2.m(l1,l2), das funktioniert, weil es eine Methode m() in Super gibt, auf dessen Signatur der Aufruf passt. Die Methode wird dann aufgrund des Referenztypen in Sub dynamisch gebunden und es wird "m2" ausgegeben.
Mein Vorgehen ist also folgendes: Ich schaue mir als erstes den Deklartionstypen der Variablen an, der die Methode aufruft (z.B. Inter). Dann suche ich mir alle Methoden in dieser Klasse (geerbt und deklariert) raus, bei denen die Signatur passt. Bei den übergebenen Parametern ist hier nur der Deklarationstyp von Bedeutung, z.B. bei s1.m(h,t) Hund H und Tier t. Sollten jetzt noch mehr als eine Methode übrig sein, wird die speziellste (most-specific-algorithm) gewählt. Anschließend schaue ich mir den dynamischen Typen von s1 an, hier wäre es Sub, und finde damit die auszuführende Methode in Sub.
Wo mache ich den Fehler? Oder habe ich irgendwas total falsch verstanden?
ich lerne gerade Java und habe ein Verständnisproblem bei einer Aufgabe. Es soll entschieden werden, ob bestimmte Methodenaufrufe vom Compiler zugelassen werden und wenn ja, welche Ausgabe es gibt. Ich bin durch die Forensuche leider nicht schlauer geworden, deshalb hoffe ich, dass mir jemand helfen kann.
Es sind folgende Klassen gegeben:
Interface Inter{
public m(Hund h, Object o)
}
abstract class Super implements Inter{
public m(Lebewesen l1, Lebewesen l2)
}
class Sub extends Super{
public m(Hund h, Object o){
System.out.println("m1");
}
public m(Lebewesen l1, Lebewesen l2){
System.out.println("m2");
}
public m(Hund h, Tier t){
System.out.println("m3");
}
}
Außerdem:
class Lebewesen{}
class Tier extends Lebewesen{}
class Hund extends Tier{}
In der main-Methode werden jetzt folgende Objekte erzeugt:
Inter s1=new Sub();
Super s2=new Sub();
Hund h = new Hund();
Tier t = h;
Lebewesen l1=new Tier();
Lebewesen l2=new Tier();
Frage:
1. beim Aufruf s1.m(h,t); wird "m1" ausgegeben. Der Deklarationstyp von s1 ist Inter, deshalb kommen nur Methoden m() in Frage, die in Inter deklariert sind. Es wird jetzt die speziellste der passenden Methoden bzgl. der Parameter gesucht, hier gibt es nur eine und die Signatur passt. Diese wird dann aufgrund des Typen der Instanz, die s1 referenziert dynamisch an die überschriebene Methode in Sub gebunden. So habe ich das zumindest verstanden.
2. wieso erzeugt der Aufruf s2.m(h,t) dann einen Compilerfehler? Die Methode in Super passt auf den Aufruf, denn die Deklarationstypen der Übergebenen Parameter sind Subtypen der Parameter in der Methodensignatur. Diese müsste doch dann genau wie in 1. dynamisch in Sub gebunden werden (also "m2" ausgeben). Falls die Methode in Inter auch in Super als abstrakte Methode existiert (dabei bin ich mir nicht sicher), dann müsste diese gewählt werden, denn sie ist spezieller oder täusche ich mich?
Ein weiterer Aufruf wäre z.B. s2.m(l1,l2), das funktioniert, weil es eine Methode m() in Super gibt, auf dessen Signatur der Aufruf passt. Die Methode wird dann aufgrund des Referenztypen in Sub dynamisch gebunden und es wird "m2" ausgegeben.
Mein Vorgehen ist also folgendes: Ich schaue mir als erstes den Deklartionstypen der Variablen an, der die Methode aufruft (z.B. Inter). Dann suche ich mir alle Methoden in dieser Klasse (geerbt und deklariert) raus, bei denen die Signatur passt. Bei den übergebenen Parametern ist hier nur der Deklarationstyp von Bedeutung, z.B. bei s1.m(h,t) Hund H und Tier t. Sollten jetzt noch mehr als eine Methode übrig sein, wird die speziellste (most-specific-algorithm) gewählt. Anschließend schaue ich mir den dynamischen Typen von s1 an, hier wäre es Sub, und finde damit die auszuführende Methode in Sub.
Wo mache ich den Fehler? Oder habe ich irgendwas total falsch verstanden?