Rückgabe ein Objekt der Unterklasse mit Generika
Mit einer abstrakten Klasse will ich eine Methode definieren, gibt "diese" für die Unterklassen:
public abstract class Foo {
...
public <T extends Foo> T eat(String eatCake) {
...
return this;
}
}
public class CakeEater extends Foo {}
Ich möchte in der Lage sein, Dinge zu tun wie:
CakeEater phil = new CakeEater();
phil.eat("wacky cake").eat("chocolate cake").eat("banana bread");
Wohl Bananen-Brot wirft eine IllegalArgumentException mit der Meldung "Kein Kuchen!"
InformationsquelleAutor Sarabjot | 2010-07-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
Bearbeiten
Ist es kein problem, zu verlangen, Unterklasse Verhalten sich in gewisser Weise über das hinaus, was die statische Typisierung überprüfen können. Wir tun das die ganze Zeit - Seiten und Seiten von Klartext angeben, wie Sie schreiben, eine Unterklasse.
Den anderen vorgeschlagenen Lösung, mit covariant return geben, muss das gleiche tun - Fragen Unterklasse Implementierer, in einfachem Englisch, die Rückkehr der Art der
this
. Diese Anforderung kann nicht angegeben werden, durch die statische Typisierung.Foo<T extends Foo<T>>
. Dies funktioniert, aber Sie können leicht erstellen Sie eine Klasse, wird die Luft zu sprengen mit einemClassCastException
beim Aufrufeat
wieclass Bar extends Foo<CakeEater>
.Dies ist die Lösung, die ich letztendlich benutzt, aber Sie werden feststellen, dass die Rückkehr hat eine unchecked cast Warnung. Während logisch macht es Sinn, dass wir casten zu T wie diese ist eine Unterklasse von T.
Ja. In einer besseren Welt, Java hätte eine
This
geben, das wäre sehr nützlich in vielen Fällen.class FakeEater extends Foo<CakeEater> { }
Nehmen Sie jetzt Notiz von der Warnung.Tom, ich habe nicht bemerkt, jede Warnung. Vielleicht ist das der Punkt deiner Antwort, dass es keine compile-Zeit-Warnung. Beim Aufruf FakeEater Essen es gibt eine compile-Zeit Ausnahme, dass der Rückgabe-Typ ist nicht der Typ FakeEater, wenn es zugewiesen wird, um eine FakeEater Feld.
InformationsquelleAutor irreputable
Den geschmackvollen Ansatz von der client-Sicht (das ist in der Regel die, die Sie wollen zu nehmen), ist die Verwendung kovariante Rückgabetypen, die wurde Hinzugefügt, um Unterstützung Generika Michael Barker Punkte aus.
Den etwas weniger geschmackvoll, aber geschmackvoller, dass ein cast ist eine
getThis
Methode:InformationsquelleAutor Tom Hawtin - tackline
Ich glaube nicht, dass Sie brauchen, generics von Java 5 (und höher) hat kovariante Rückgabetypen, z.B.:
Es funktioniert, wenn Sie die Umwandlung dieser als Typ T und Warnmeldungen unterdrücken. Der Grund dafür, dass es wieder der Typ der Unterklasse ist, weil: methodTakesCakeEater( (neue CakeEater).Essen("Kuchen").Essen("pie"); methodTakesCakeEater braucht eine CakeEater parameter.
Wenn eine Lösung enthält
@SuppressWarnings
es sollte nicht als eine Lösung. Nur meine zwei Cent.Mach dir keine sorgen über die Warnungen, wenn du etwas ausgefallenen Sachen.
Auch ich denke, das ist nicht "kantig" Dinge erfordern einen zu ignorieren oder zu unterdrücken Warnungen
InformationsquelleAutor Michael Barker
Ansatz, den ich verwendet habe, bevor Sie zu erreichen, ein ähnliches Verhalten ist für die Unterklasse übergeben, deren Typ in einem Konstruktor der (generified) übergeordneter Typ. Durch die Möglichkeit, Haftungsausschluss ich wurde die Generierung der Unterklassen auf die Fliegen und inheritence war ein bisschen schummeln, um zu halten mein code-Generierung einfach, da das immer mein Erster Instinkt ist, zu versuchen, entfernen Sie die erweitert-Beziehung insgesamt.
InformationsquelleAutor CurtainDog