Ich bin ein wenig verwirrt darüber, wie Java Generika behandeln Vererbung / Polymorphismus.
Nehmen Sie die folgende Hierarchie an -
Tier (Elternteil)
Hund - Katze (Kinder)
Nehmen wir also an, ich habe eine Methode doSomething(List<Animal> animals)
. Nach allen Regeln der Vererbung und des Polymorphismus würde ich annehmen, dass ein List<Dog>
ist a List<Animal>
et un List<Cat>
ist a List<Animal>
- und kann daher an diese Methode übergeben werden. Dem ist nicht so. Wenn ich dieses Verhalten erreichen will, muss ich der Methode explizit sagen, dass sie eine Liste einer beliebigen Unterklasse von Animal akzeptieren soll, indem ich sage doSomething(List<? extends Animal> animals)
.
Ich verstehe, dass dies das Verhalten von Java ist. Meine Frage ist pourquoi ? Warum ist Polymorphismus im Allgemeinen implizit, aber wenn es um Generika geht, muss er angegeben werden?
22 Stimmen
Und eine völlig unabhängige Grammatikfrage, die mich gerade beschäftigt - sollte mein Titel "warum" lauten? sind nicht Javas Generika" oder "Warum ist nicht Java's generics"? Ist "Generika" Plural wegen des s oder Singular, weil es eine Einheit ist?
28 Stimmen
Generika, wie sie in Java verwendet werden, sind eine sehr schlechte Form des parametrischen Polymorphismus. Setzen Sie nicht zu viel Vertrauen in sie (wie ich es früher getan habe), denn eines Tages werden Sie hart an ihre erbärmlichen Grenzen stoßen: Surgeon extends Handable<Scalpel>, Handable<Sponge> KABOOM! Macht nicht berechnen [TM]. Das ist die Einschränkung der Java-Generik. Jede OOA/OOD kann gut in Java übersetzt werden (und MI kann sehr schön mit Java-Schnittstellen gemacht werden), aber Generika sind einfach nicht geeignet. Sie sind gut für "Sammlungen" und prozedurale Programmierung, dass sagte (das ist, was die meisten Java-Programmierer sowieso tun, so...).
8 Stimmen
Die Superklasse von List<Dog> ist nicht List<Animal>, sondern List<?> (d. h. eine Liste unbekannten Typs). Generics löscht Typinformationen im kompilierten Code. Dies geschieht, damit Code, der Generics verwendet (Java 5 und höher), mit früheren Versionen von Java ohne Generics kompatibel ist.
5 Stimmen
Verwandte SO-Fragen - Was nützt es, <? extends SomeObject> statt <SomeObject> zu sagen?
0 Stimmen
Ich möchte nur hinzufügen, dass es ein offizielles Java-Tutorial zu diesem Thema gibt: docs.oracle.com/javase/tutorial/extra/generics/subtype.html
10 Stimmen
@froadie, da niemand zu antworten schien... es sollte definitiv heißen "warum sind Javas Generics nicht...". Das andere Problem ist, dass "generisch" eigentlich ein Adjektiv ist und "Generika" sich auf ein fallengelassenes Pluralnomen bezieht, das durch "generisch" modifiziert wird. Man könnte sagen "diese Funktion ist eine generische", aber das wäre umständlicher als "diese Funktion ist generisch". Allerdings ist es auch etwas umständlich, zu sagen "Java hat generische Funktionen und Klassen", anstatt einfach "Java hat Generika". Als jemand, der seine Magisterarbeit über Adjektive geschrieben hat, denke ich, dass Sie über eine sehr interessante Frage gestolpert sind!
1 Stimmen
List<A>
hat keine Beziehung zuList<B>
unabhängig von der Beziehung zwischen den Klassen A und B.0 Stimmen
@dantiston Generics könnte als kollektiver Singular betrachtet werden, in diesem Fall funktioniert "isn't" sehr gut.
0 Stimmen
@SyntaxT3rr0r In Ihrem Beispiel würde meine Lösung darin bestehen, eine Superschnittstelle von
Scalpel
ySponge
(wahrscheinlich mit einem Namen wieSurgeonItem
), dann deklariertSurgeon extends Handable<SurgeonItem>
.1 Stimmen
@rai.skumar
List<?>
ist nicht der einzige wirksame Supertyp vonList<Dog>
. Andere Beispiele sindList<? extends Dog>
yList<? super Dog>
. Außerdem kann jede Variante der vier (<Dog>
,<? super Dog>
,<? extends Dog>
,<?>
), angewandt auf einen Supertyp vonList
gelten ebenfalls:Collection<Dog>
,Iterable<? super Dog>
, usw.. Überall, wo Sie einen Verweis auf eines dieser Elemente haben, können Sie auch eineList<Dog>
. AuchList<? extends Animal>
yList<? super Chihuahua>
.1 Stimmen
Verwandt: Was ist PECS (Producer Extends Consumer Super)?