Slyh: Frage zu Polymorphie in Java

Beitrag lesen

Hallo,

Aber: nach unseren Wissen kann man über ein Referenz auf eine Vaterklasse nicht Attribute zugreifen, die in der Sohnklasse hinzugefügt wurden (hier double t). Dies passiert aber in diesem Fall, wenn auch indirekt über die überschriebene Methode f.

Ja. Die Methode gehört zu C und kennt dann natürlich alles, was zur
Klasse gehört.

Wird hier intern ein expliziter Downcast durchgeführt, oder was ist der Grund das dies funktioniert?

Der Compiler denkt nicht in Casts.

Ein Cast ist eigentlich nur ein Hinweis an den Compiler, daß es sich
bei einem konkreten Objekt um eine Instanz einer anderen (üblicherweise
weiter unten in der Hierarchie befindlichen) Klasse handelt. Den
Hinweis gibt der Mensch, der das zum Zeitpunkt der Entwicklung weiß.
Wenn der Mensch eine falsche Angabe macht, wird während das während
der Ausführung(!) bemerkt und eine ClassCastException geworden.

Polymorphismus hat überhaupt nichts mit Casts zu tun. Beim konkreten
Aufruf der Methode "f" wird die passende Methode (zur Laufzeit!)
ermittelt und aufgerufen. Die Laufzeitumgebung weiß natürlich jederzeit
welches konkrete Objekt sich hinter einer Referenz versteckt.
Entsprechend wird das passende "f" im passenden Objekt aufgerufen, so
daß die Methode "f" vollen Zugriff auf das Objekt hat. Es handelt sich
ja schließlich um eine Methode des Objekts.

Man muß hier wirklich ein bißchen zwischen Compile- und Ausführzeit
unterscheiden. Casts dienen dazu, dem Compiler mitzuteilen, daß es
sich -- grob gesprochen -- bei einem Objekt eigentlich um ein
höherwertiges Objekt handelt, als er aktuell denkt. Das ist nötig, um
Zugriff auf die Methoden oder Attribute zu bekommen, die das höher-
wertige Objekt besitzt. Der Compiler kann das selbst nicht wissen,
weil der Inhalt der Referenz (je nach Typ) beliebig während der
Laufzeit gesetzt werden kann. Der Mensch hingegen weiß (optimalerweise)
wobei es sich wirklich handelt und fügt daher den Cast ein.

Zum Beispiel kann ich jedes konkrete Objekt (z.B. String) immer als
Referenz auf ein Object-Objekt verwenden. Dann steht mir nur das
zur Verfügung, was Object anbietet. Alles andere ist nicht verfügbar,
weil der Compiler ja nicht wissen kann, daß in der Object-Referenz
in Wirklichkeit ein String steht. (Während der Laufzeit weiß die
Laufzeitumgebung das hingegen sehr wohl.)
Um jetzt trotz Object-Referenz auf Inhalt des String-Objekts zugreifen
zu können, muß das Object in das konkretere "String" gecastet werden.
Dann weiß der Compiler(!), daß es sich in Wirklichkeit um einen String
handelt und erlaubt weitere Operationen.

Zur Laufzeit, also wenn es zum Polymorphismus kommt und die passende
Methode in der Hierarchie "gefunden" werden muß, ist der Laufzeit-
umgebung natürlich klar, welches tatsächlice Objekt sich hinter einer
Referenz wirklich verbirgt, also kann die Methode aufgerufen werden.
Diese muß die Attribute ohnehin kennen, weil ja sonst auch keine
Kompilierung möglich gewesen wäre.

Der Compile-Vorgang funktioniert hier auch ohne dieses wissen, weil
die Methoden eine definierte Parameterliste haben und den gleichen
Rückgabewert besitzen, auch wenn sie weiter unten in der Hierarchie
nochmal überschrieben werden. Es ist daher immer möglich, den Quellcode
zu kompilieren, weil die Methode immer existiert.

Gruß
Slyh