Vererbung und Polymorphie

Status
Nicht offen für weitere Antworten.

trunkz0r

Mitglied
Ich hoffe, das ist das richtige Forum, wenn nicht bitte verschieben :)

Die Grundprinzipien von Vererbung und Polymorphie sind mir klar.
Allerdings gibt es da ein Phänomen, das ich mir nicht erklären kann. Am besten ich erklärs mit nem Beispielcode:

Es gibt 3 Klassen, eine Vaterklasse A, eine Unterklasse B und eine auszuführende Klasse C:
[highlight=Java]public class A{
public void test(A a){
System.out.println("Methode in A wurde aufgerufen");
}
}
[/highlight]
[highlight=Java]public class B extends A{
public void test(B b){
System.out.println("Methode in B wurde aufgerufen");
}
}
[/highlight]
[highlight=Java]public class C{
public static void main(String[] args){
A ref1 = new B();
B ref2 = new B();
ref1.test(ref2);
}
}
[/highlight]

Was ich daran nicht verstehe, ist wieso die Methode in A aufgerufen wird. Mir ist klar, dass wegen der unterschiedlichen Signatur nichts überschrieben wird.
Eine Möglichkeit wäre, dass, weil ref1 eine Variable von Typ A ist, das ganze implizit zu A gecastet wird. Dann würden doch aber gar keine Funktionen aus B zur Verfügung stehen, was aber nicht der Fall ist (wenn ich die Methoden z.B. überschreiben lasse, indem ich die Parameter wegnehme, wird immer die Methode aus Klasse B ausgeführt).

Bin für jede Hilfe dankbar :rtfm:
 
Zuletzt bearbeitet:

0x7F800000

Top Contributor
Ich vermisse irgendwie ein "extends"...
...und überlege mir schonmal, was du sonst noch etwas übersehen haben könntest ???:L

Also, wenn ich einfach so annehme, dass da lediglich das extends fehlt, erscheint mir da alles logisch...

Du hast es doch selbst gesagt:
B erweitert A
B kriegt die methode mit der signatur "void test(A)" einfach vererbt
B überschreibt NICHT die methode mit der Signatur "void test(A)", sondern erstellt eine neue mit der Signatur "void test(B)"

ref1 ist vom Typ A deklariert und vom typ B definiert, ordnet also signaturen wie folgt methoden zu:
Code:
ref1{
  "void test(A)" -> die methode aus A
  "void test(B)" -> die methode aus B
}

wenn du versuchst, diesen code auszuführen:
Code:
ref1.test(ref2);
dann schaut sich der compiler das an, stellt fest dass da nur die Signatur "void test(A)" angebracht ist, fragt dynamisch, was das objekt ref1 an methoden mit der Signatur "void test(A)" zu bieten hat, und das ist natürlich die ganz normale methode aus A...


_______________
Hättest du das überschrieben, also:
Code:
class B extends A{
  @Override
  public void test(A a){
    Sys...out..blah("B");
  }
}

dann würde ref1 natürlich folgende methoden den signaturen zuordnen:
Code:
ref1{
  "void test(A)" -> die methode aus B, die aus A wurde ja dadurch überschrieben
}

und beim aufruf
Code:
ref1.test(ref2);
würde da auch "B" rauskommen...

Okay so?:bahnhof:
 
Zuletzt bearbeitet:

hdi

Top Contributor
dann schaut sich der compiler das an, stellt fest dass da nur die Signatur "void test(A)" angebracht ist, fragt dynamisch, was das objekt ref1 an methoden mit der Signatur "void test(A)" zu bieten hat, und das ist natürlich die ganz normale methode aus A...
Das ist nicht ganz korrekt finde ich. Er sucht erstmal in der Klasse A nach einer Methode mit der Singatur: void test(B), und findet eine solche Methode nicht.
Allerdings kann er über "Reference Widening" ein B zu einem A casten, wie du schon richtig geahnt hast. (Weil B IS-A A)
Und das macht er dann auch.

Warum aber ruft er nicht die Methode void(B) der Klasse B auf, immerhin passt das ja von dem Parameter her viel genauer (sogar exakt)?
Antwort: Der Compiler kennt nicht den wahren Typ einer Variablen:

A a = new B();

für den Compiler ist das "a" eine Referenz auf ein A, NICHT auf ein B.
Das Reference Widening übernimmt auch die JVM, nich der Compiler. Die JVM sagt dem Compiler einfach: Jaja, passt schon, kannste aufrufen.
Der Compiler weiss aber noch immer nicht, dass das ein B ist, oder ein X, oder sonst was. Er glaubt der JVM einfach.

Deshalb durchscht er die Klasse B gar nicht erst. Er weiss nicht mal, dass es diese Klasse gibt!

Soweit sollte das nachvollziehbar sein. Die Frage ist, warum ruft er die Version von B auf, falls man die Methode aus A überscheibt.
Hier mischt sich wieder die JVM ein: Sie sagt dem Compiler, dass es eine andere Methode gibt, die genau die selben Parameter erwartet.
In diesem Fall wird die Methode der Klasse aufgerufen, von dem der Typ WIRKLICH ist.

Zusammenfassung: Es geht nicht darum, welche Methode am ehesten zutrifft von den Parametern. Es geht darum, welche Methode genau der Klasse, die der Compiler sieht (A), am ehesten zutrifft. Und das ist eben (A a) durch Reference Widening.
Erst wenn Methoden EXAKT gleich sind, also überschrieben, wählt er die passendere aller verfügbaren aus den Klassen, indem die JVM ihm sagt von welchem Typ das Objetk jetzt wirklich ist.

Die JVM ist sozusagen der Gehilfe bei der Methoden-Auswahl. Entweder man kann die Methode, die der Compiler wählen würde (immer die des Typs der Variablen), irgendwie casten, dann bestätigt das die JVM.
Oder es gibt wirklich gleiche MEthoden, dann übernimmt die JVM eine Korrektur der Auswahl und reicht es an den Compiler zurück.

Anm: Dieses Gerede von wegen "die JVM sagt dem Compiler" usw kann man nicht wörtlich nehmen, und ist sicher nicht "korrekt". Zur Laufzeit gibt es den Compiler gar nicht. Aber zumindest von der Logik her funktioniert es so wie beschrieben, glaube und hoffe ich zumindest ;)
 
Zuletzt bearbeitet:

trunkz0r

Mitglied
whoops, genau das extends bei klasse B hab ich vergessen :)

also so weit hab ich das ja alles verstanden, aber das erklärt nicht wieso bei
ref1.test(ref2);

die methode aus A ausgeführt wird. die methode aus B würde ja ebenfalls von den parametern passen, wär sogar etwas spezifischer.

was auch noch anzumerken ist, ist dass wenn ich statt
A ref1 = new B()

das so schreib
B ref1 = new B()

dann wird auch tatsächlich die methode aus B aufgerufen.

edit: das habe ich vor dem oberen post geschrieben :p
 

faetzminator

Gesperrter Benutzer
natürlich erklärt es das.
wenn du ein Objekt A hast, hast du (nebst den Object Methoden) folgende zur Verfügung:
- void test(A)
Wenn du ein Objekt B hast, hast du grundsätzlich
- void test(B)
aber natürlich auch noch
- void test(A) aus A

nun, dein ref1 ist ein A und hat damit alle Methoden von sich und seiner Superklasse(n), sicher nicht aber der Subklasse(n). Das ist, als würdest du fragen, warum Object keine print() Methode hat, die von ihm geerbte Klasse Stream kann das ja....

Gruss, faetzminator
 

Landei

Top Contributor
Was du willst könnte vielleicht so gehen (ungetestet):

[highlight=Java]public class A<X extends A<X>>{
public void test(X x){
System.out.println("Methode in A wurde aufgerufen");
}
}
[/highlight]
[highlight=Java]public class B extends A<B>{
public void test(B b){
System.out.println("Methode in B wurde aufgerufen");
}
}
[/highlight]
 

hdi

Top Contributor
nun, dein ref1 ist ein A und hat damit alle Methoden von sich und seiner Superklasse(n), sicher nicht aber der Subklasse(n).
Das stimmt nur halb. Das ref1 ist ein B, nur für den Compiler ist es ein A. Wie gesagt, sobald du die Methode überschreibst, wird die Version von B aufgerufen.
Wäre mal interessant zu wissen wie genau das funzt, meine Erklärung vorhin war schon extrem wischiwaschi. (wenn auch vom Verhalten her richtig)
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Vererbung - Polymorphie Java Basics - Anfänger-Themen 37
G Polymorphie, Vererbung, statischer Typ, Laufzeittyp Java Basics - Anfänger-Themen 2
D Vererbung / Polymorphie Java Basics - Anfänger-Themen 5
H Polymorphie Verständnisproblem Vererbung/Polymorphie Java Basics - Anfänger-Themen 4
M OOP Polymorphie/Vererbung Verständnisproblem Java Basics - Anfänger-Themen 2
M Vererbung Enum Vererbung/Polymorphie Java Basics - Anfänger-Themen 2
S Polymorphie und Vererbung Java Basics - Anfänger-Themen 6
Z Vererbung oder Polymorphie? Java Basics - Anfänger-Themen 5
S Polymorphie und Vererbung Java Basics - Anfänger-Themen 25
imocode Vererbung Problem mit Vererbung Java Basics - Anfänger-Themen 2
L Java- Vererbung Java Basics - Anfänger-Themen 4
ineedhelpinjava Vererbung Java Basics - Anfänger-Themen 12
ineedhelpinjava Vererbung Java Basics - Anfänger-Themen 1
I JSON / XML Struktur mit Vererbung / Interfaces Java Basics - Anfänger-Themen 0
M Interface oder Vererbung? Java Basics - Anfänger-Themen 12
M Vererbung Java Basics - Anfänger-Themen 6
M Designentscheidung von Attributen/Methoden im Falle von Vererbung Java Basics - Anfänger-Themen 8
M Generics Vererbung Listen Java Basics - Anfänger-Themen 2
A Methoden Vererbung und Interface Java Basics - Anfänger-Themen 14
D Klassen und Vererbung Java Basics - Anfänger-Themen 2
U Vererbung Java Basics - Anfänger-Themen 7
D Vererbung Java Basics - Anfänger-Themen 3
K Schleife berechnet kein Ergebnis (Vererbung) Java Basics - Anfänger-Themen 6
00111010101 Objektorientiertes Programmieren mit Vererbung (Zahlen in Array verschwinden) Java Basics - Anfänger-Themen 3
W Zur Vererbung: Wann und wie? Java Basics - Anfänger-Themen 35
H Datenkapselung, Vererbung und UML Java Basics - Anfänger-Themen 16
districon Super-Stichwort/ Vererbung Java Basics - Anfänger-Themen 3
YaU Vererbung erstellt NullPointerException? Java Basics - Anfänger-Themen 4
1 Vererbung Klassenattribute Java Basics - Anfänger-Themen 9
TimoN11 Frage zu Java-Vererbung (Cast) Java Basics - Anfänger-Themen 5
N Thema Vererbung Java Basics - Anfänger-Themen 31
A Vererbung Vererbung Übung Java Basics - Anfänger-Themen 5
B Vererbung - Sichtbarkeitsmodifikation - protected Java Basics - Anfänger-Themen 10
B Best Practice Unschlüssig ob Vererbung oder Interface Java Basics - Anfänger-Themen 2
G Java Vererbung Java Basics - Anfänger-Themen 8
Y Vererbung Konto - Anfangsprobleme Java Basics - Anfänger-Themen 7
A Vererbung Klassen im Bezug auf Auto´s Java Basics - Anfänger-Themen 18
A Klassen Vererbung und zusätzliche Unterklassen Java Basics - Anfänger-Themen 23
M Vererbung mit Enums Java Basics - Anfänger-Themen 8
Kirby.exe Vererbung im Detail erklärt? Java Basics - Anfänger-Themen 9
N Modellierung, vererbung, Java Basics - Anfänger-Themen 163
M Fehlendes Verständnis für dynamische Bindung und Vererbung Java Basics - Anfänger-Themen 13
W OOP Vererbung im Computerspiel Java Basics - Anfänger-Themen 7
J Probleme mit Vererbung Java Basics - Anfänger-Themen 4
I Vererbung Java Basics - Anfänger-Themen 13
W OOP Vererbung und Problem bei Zählschleife in einer Methode Java Basics - Anfänger-Themen 10
W Methoden Verständnisfrage Vererbung von Methoden Java Basics - Anfänger-Themen 14
V Vererbung Java Basics - Anfänger-Themen 2
J Frage zur Vererbung Java Basics - Anfänger-Themen 1
J Vererbung Java Basics - Anfänger-Themen 3
U Was löst meine NullPointerException aus? (Vererbung) Java Basics - Anfänger-Themen 12
O Vererbung Ueben mit kleiner Datenstruktur von Räumen Java Basics - Anfänger-Themen 10
O Umgang mit Vererbung verstehen Java Basics - Anfänger-Themen 4
A Vererbung/Interfaces/Generics Java Basics - Anfänger-Themen 12
O Vererbung änderung des Konstruktors Java Basics - Anfänger-Themen 8
L Vererbung Java Basics - Anfänger-Themen 5
E HashMap+Vererbung Java Basics - Anfänger-Themen 11
E Vererbung super-Methoden Aufruf Java Basics - Anfänger-Themen 3
B Java Vererbung Fragen (zu Code Beispiel) Java Basics - Anfänger-Themen 3
A Objekterstellung bei der Vererbung Java Basics - Anfänger-Themen 7
P Vererbung Warum funktioniert die Vererbung hier nicht Java Basics - Anfänger-Themen 14
S Vererbung Java mehrfach Java Basics - Anfänger-Themen 10
B Objekte zählen/ Vererbung/ Kopplung/ Interface/ Abstract Class Java Basics - Anfänger-Themen 5
A Klassen Vererbung privater Methoden und Member Java Basics - Anfänger-Themen 12
A Konstruktoren Vererbung Java Basics - Anfänger-Themen 3
ReinerCoder Vererbung von JFrame in einer Klasse entfernen Java Basics - Anfänger-Themen 5
W Vererbung, abstract und Konstruktoren Java Basics - Anfänger-Themen 30
J Vererbung und Methodenaufruf Java Basics - Anfänger-Themen 11
H Vererbung mit private instanzvariablen Java Basics - Anfänger-Themen 9
S Vererbung Funktionsweise Code zur Vererbung Java Basics - Anfänger-Themen 1
C Methoden Vererbung private Attribute/public Methoden Java Basics - Anfänger-Themen 4
S Verständnis Vererbung Java Basics - Anfänger-Themen 3
D JavaFX Vererbung Java Basics - Anfänger-Themen 2
U Vererbung Generizität und Vererbung Java Basics - Anfänger-Themen 4
A Vererbung bei Klassen mit Objekt der Klasse im Konstruktor Java Basics - Anfänger-Themen 4
K Vererbung Octagon von Circle Java Basics - Anfänger-Themen 0
B Hilfe bei Vererbung Java Basics - Anfänger-Themen 2
D Vererbung Frage zum Klassenaufbau mit Vererbung Java Basics - Anfänger-Themen 1
T Vererbung und interface. Java Basics - Anfänger-Themen 1
S Gehaltsberechnung (Vererbung, abstrakte Methoden) Java Basics - Anfänger-Themen 6
S Vererbung Java Basics - Anfänger-Themen 1
F Vererbung in zwei Richtungen? Java Basics - Anfänger-Themen 14
O Vererbung Java Basics - Anfänger-Themen 5
MiMa Vererbung Theorie OK, Praxis ?? Java Basics - Anfänger-Themen 4
Arif Vererbung Vererbung Variablen überschreiben Java Basics - Anfänger-Themen 1
C Vererbung - Ausgaben bestimmen Java Basics - Anfänger-Themen 6
S Vererbung Java Basics - Anfänger-Themen 10
L Setter und Getter/Vererbung Java Basics - Anfänger-Themen 6
C Konstruktoren und Vererbung Java Basics - Anfänger-Themen 2
J Kleinere Frage zur Vererbung/Objekterzeugung Java Basics - Anfänger-Themen 2
G Vererbung Java Basics - Anfänger-Themen 12
J Vererbung privater Variablen Java Basics - Anfänger-Themen 7
J Vererbung Vererbung von Methoden Java Basics - Anfänger-Themen 6
B Vererbung Java Basics - Anfänger-Themen 12
K Vererbung (super) Java Basics - Anfänger-Themen 2
A ArrayQueue mit Exceptions und Vererbung Java Basics - Anfänger-Themen 3
J Java: static bei Vererbung Java Basics - Anfänger-Themen 5
C Vererbung Java Basics - Anfänger-Themen 4
L Vererbung Java Basics - Anfänger-Themen 3
J Klassenorganisation | Vererbung Java Basics - Anfänger-Themen 1

Ähnliche Java Themen

Neue Themen


Oben