Polymorphie Aufgaben

  • 35 Antworten
  • Letztes Antwortdatum
@Jail kein super!

@ deek

Die Referenz - Type wird immer zu Runtime zugewiesen.

Die "Methodensignatur" wird schon zu Compilezeit zugewiesen.
Sprich das Objekt weiß, welche Methoden es hat (Kein dynamisches Binden).

Das ganze hängt an den Referenztypen.

Laut Oracle.

---

PS:
Es wird auch schon zu Compilezeit, bestimmt welche Methode ausgeführt wird. Nur die Zuordnung des Types geschieht zu Laufzeit. So etwas nennt man statisches Binden.
 
Zuletzt bearbeitet:
DagobertDokate schrieb:
Naja polymorphie scheint öfters für Probleme zu sorgen :D

Und mit Covariantem Polymorphismus haben wir noch garnicht angefangen :D
 
Einfach alles nur angewandte Mengenlehre.

Alles halb so wild. ;)
 
Covariantem Polymorphismus
Jetzt fängt es wohl an wo mein Wortschatz mich auch verlässt.... :D

Erzähl mir mehr ;)

lg. Dagobert
 
Sagt mir jetzt auch nicht.

Aber es gibt Varianten der Polymorphie, in der Kovarianz auftritt. (Generic)
 
:D:D

Wenn du dich Quälen willst, guckst du hier: https://de.wikipedia.org/wiki/Kovarianz_und_Kontravarianz

Auch wenn der Artikel etwas unglücklich formuliert, dass Java Kontravariant sei. Das kann man zwar so sagen (weil A a = new B() geht), aber der Polymorphismus(!) ist es nicht, weil

Code:
class A {
  public void foo( B b ) { } // X
}
class B extends A {
  public void foo( A a ) { } // Y
}
new B().foo( new B() ) --> X
 
Zuletzt bearbeitet:
Vielleicht Han ich es jetzt kapiert ... Ohne jetzt nochmal alles zu revidieren behaupte ich mal dass...ausgehend von seinem ersten Beispiel des TE ... Wenn man in die Klasse Oben die Methode
gg (Unten u) implementiert hätte DANN hätte er M ausgegeben? !

Der ursprüngliche Beitrag von 16:53 Uhr wurde um 17:12 Uhr ergänzt:

markus.tullius schrieb:
Einfach alles nur angewandte Mengenlehre.

Alles halb so wild.

So hab ich das noch nicht betrachtet aber das ist genial(auch wenn Mengenlehre keine Wissenschaft ist)...sowie im wikiartikel auch mit den Funktionen und dem Uml Diagramm
 
Zuletzt bearbeitet:
Jaiel schrieb:
Wenn man in die Klasse Oben die Methode
gg (Unten u) implementiert hätte DANN hätte er M ausgegeben? !

Ja, dann würde auch ich ein "M" erwarten.
 
  • Danke
Reaktionen: Jaiel
OK jetzt drehen sich die Räder wieder im Kopf danke...Deine Erklärungen waren auch gut im Nachhinein betrachtet
 
Ich verstehs immernoch nicht, also ich mach das iwie vom Gefühl her sitze schon seit Zwei Tagen und ich bin selber ein Compiler in Person geworden xD Ich könnte einem anderen nicht erklären wieso ich was ausgebe aber ich kann es anwenden :lol:
 
Also ich denke ich Versuchs mal mit einfachen Worten zu erklären:

Zu deiner ersten Aufgabe...

ff ist zur compile zeit ein Oben mit 2 Methoden gg (Oben) und gg (Mitte).
Während das Programm läuft wird es als ein Mitte Objekt deklariert was ja ok ist weil Mitte ein oben ist.
Es besitzt die Methoden gg (Oben) die sie overrided aus der Basis klasse , die vererbte gg (Mitte) und die neue gg (Unten)

So wenn du jetzt die Methode gg (unten) aufrufen willst mit dem ff dann findet die maschine diese nicht da ff eigentlich ein Oben ist und nur gg (oben) und gg (mitte) kennt.
Also nimmt es die geerbte gg (mitte) weil diese am näherten kommt.

Wenn du also ein Basisklassenobjekt mit einem unterklassenobjekt initialisiert wird es durch einen methodenaufruf nur eine überschriebene Methode in der unterklasse aufrufen die es auch in der Basisklasse gibt.

Oben kennt kein gg (Unten) also nimmt es gg (Mitte)

Aber hättest du eine Methode gg (unten) in der Basis klasse die ein S ausgibt und du würdest das gleiche Beispiel ausführen dann würde er die überladene Methode gg (unten) aus Mitte nehmen da er diese kennt und sieht das in Mitte eine nennen wir es mal aktuelle/bessere Version dieser Methode der Oberklasse vorliegt.

Also nochmal kürzer:
Oberklassen die mit Hilfe von Unterklassen initialisiert werden und overgeloadete Methoden aus der Unterklasse aufrufen möchten müssen die selbe Methode mit derselben Signatur besitzen (die Unterklasse überschreibt dementsprechend die Methode mit derselben Signatur )

Deshalb ruft ff.gg (ff) die neue aktualisierte bessere Methode, mit derselben Signatur wie in der Basisklasse, aus Mitte auf.

Und ff.gg (uu) eben nicht die gg (unten) in Mitte auf weil es in der Basisklasse keine Methode mit der Signatur gg (Unten) gibt

Der ursprüngliche Beitrag von 20:19 Uhr wurde um 20:23 Uhr ergänzt:

Hab ich das so richtig erklärt @alleanderendiesichsauskennen
 
  • Danke
Reaktionen: programm2008
omg ich habe es endlich verstanden :smile: Vielen Dank :DD

Wenn du also ein Basisklassenobjekt mit einem unterklassenobjekt initialisiert wird es durch einen methodenaufruf nur eine überschriebene Methode in der unterklasse aufrufen die es auch in der Basisklasse gibt.


Oben kennt kein gg (Unten) also nimmt es gg (Mitte)


Das hier waren die entscheidenden lines auf die ich nicht gekommen bin. Habs gerade ausprobiert und du hast Recht :love:
 
Fast richtig.

Jede Methode hat eine Signatur, den Namen und den Typ des Arguments.

Alle Methoden gg(Mitte a) haben die gleiche Signatur gg+Mitte.

Zum 3 Fall:

Es wird eine Methode mit der Signatur gg+Unten gesucht. Die Schnittstelle stellt die Methode nicht zur Verfügung. Also wird überprüft, ob es eine Methode mit der Signatur gg+Mitte gibt
(Ein Schritt hoch in den Baum. Vererbung ist eigentlich eine Erweiterung. Ein Stack von Typen, in den bei jeder Vererbung ein neuer Typ abgelegt wird. Der Compiler arbeitet jetzt den Stack von hinten ab. Last In - Frist Out. Jetzt sucht er nach einer Methode gg+Mitte).
Und es wird eine Signatur gefunden : gg+Mitte.
Und die gg+Mitte Methode eines Objekt von Typ Mitte gibt den Wert "L" aus.

Oben ist nur eine Hülle für ein Objekt Mitte. Der Typ ändert sich scheinbar, aber der dazugehörige Code bleibt gleich.

Noch eine Denkaufgabe, was passiert, wenn ein Typ eines Objekt über die Signatur festgelegt wird. Alle Objekte, welche die gleichen Signaturen haben, sind vom gleiche Typ. Erweitere ich den Typ um eine Methode, erbt ein Objekt mit der erweiterten Signaturen vom ursprünglichen Objekt.

Und ja, es gibt Programmiersprachen, die so gestrickt sind.
 
So jetzt noch eine Bonusaufgabe für alle Profis:

Gegeben
Code:
public interface A {}
public interface B {}

public class C implements A,B {}

public class D {
    public void method(A a) {
        System.out.println("A");
    }

    public void method(B b) {
        System.out.println("B");
    }
}

Aufruf:
Code:
D d = new D();
C c = new C();

d.method(c);

Was ist die Ausgabe? :biggrin::eek:
 
Boa entweder runtime error oder A und/oder B
echt keine Ahnung c implementiert ja beide Interfaces welche wird also genommen?
Die zuerst angegebene?
 
Die IDE meckert, und das Programm stürzt ab. ;)
 
Zurück
Oben Unten