Verwenden von Java-Generics, um sicherzustellen, dass das empfangene Argument dasselbe ist wie die Klasse oder der Subtyp davon

9

Ich habe eine neue Frage.

%Vor%

Ich möchte, dass die Partnermethode in den konkreten Implementierungen nur Parameter ihres Typs oder Untertyps erhält. Eine Lösung besteht darin, mithilfe von Generika Animal als:

zu definieren %Vor%

Aber jemand kann das immer noch als

missbrauchen %Vor%

wo ein Bär eine Partnerschaft mit Lion anstrebt. Gibt es eine Möglichkeit, dass ich es an den Typ und die Subtypen von this

binden kann?

Ich habe versucht, die vorhandenen Fragen zu durchsuchen, und irgendwie finde ich, dass das Design der Schnittstelle selbst fehlerhaft ist. Wenn jemand darauf hinweisen kann, warum dies falsch ist oder der richtige Weg, um dies zu erreichen, würde es sehr geschätzt werden.

Danke!

    
Kilokahn 11.07.2012, 06:07
quelle

5 Antworten

2

Es gibt keine Möglichkeit, dies auf der Schnittstellenebene zu erzwingen, da dies aus Sicht des -Typs Sicherheit nicht sinnvoll ist. Was ist, wenn es möglich ist, ein class Bear implements Animal<Lion> zu definieren? Für sich ist es typsicher (d. H. Wirft keine unerwartete ClassCastException usw.) - das ist der springende Punkt, für den Generics ist.

Aus der Sicht der Typsicherheit benötigen Sie höchstwahrscheinlich nur interface Animal<T> (analog zu interface Comparable<T> ). Ja, dies wird es jemandem erlauben, seltsame Klassen zu definieren, die Animal mit einem Typparameter implementieren, der eine völlig unabhängige Klasse ist. Na und? Es ist nichts falsch mit dem per se .

An den Stellen, an denen diese Schnittstelle verwendet wird, können sie die gewünschte Beziehung wie public <T extends Animal<? super T>> void someMethodThatUsesAnimal(T animal) erzwingen. Da es nur an den Stellen ist, an denen verwendet wird , ist es wirklich wichtig, ob sich die Methode partner selbst als Parameter verwendet. Dies ist analog zur Verwendung von Comparable (z. B. public <T extends Comparable<? super T>> void sort(List<T> list) )

    
newacct 11.07.2012, 18:03
quelle
1

Ich denke nicht, dass Sie dies zur Kompilierzeit erzwingen können. Bitte sehen Sie sich die Problemumgehung an, die dies zur Laufzeit sicherstellt.

%Vor%

Ich habe diese Idee von Java-Generika Erzwinge den Rückgabetyp der abstrakten Methode

Hoffe, das hilft.

    
krishnakumarp 11.07.2012 06:36
quelle
0

newacct hat auf die Frage eine sehr schöne Antwort gegeben und seine Analogie zu vergleichbar gemacht. Die Pflicht sicherzustellen, dass die beiden Objekte für die Partnerschaft an den Ort der Verwendung delegieren, nämlich Tiere in diesem Fall. Hier mit Beispielcode für Klarheit angeben:

%Vor%     
Kilokahn 13.07.2012 06:27
quelle
0

Sie können dies jedes Mal erzwingen, wenn jemand ein Animal -Objekt als Parameter an eine Methode übergibt. Wenn Sie z. B. eine Liste aller Tiere in Ihrem Zoo verwalten, können Sie die Klasse der Liste erweitern und die Methode add() mit dieser generischen Version überschreiben:

%Vor%

Diese Methode akzeptiert alle Animal<itself> , aber keine Animal<something else> . Auf diese Weise ist es immer noch möglich, dass jemand Bear extends Animal<Lion> definiert, aber dieser Bär ist in deinem Zoo nicht mehr erlaubt, denn wenn du ihn als Argument an add() übergibst, löst dieser Aufruf eine Kompilierungszeitbegrenzung aus Nicht übereinstimmender Fehler.

Um so komplizierter ist es, diese Konvention für den Rückgabetyp einer Methode durchzusetzen. Das Urteil steht noch nicht fest:

Erzwingen des Java-Methode-Rückgabetyps zum Anpassen Bestimmte generische Signatur

    
Markus A. 30.11.2012 16:28
quelle
0

Sie können Ihre Schnittstelle auch so definieren:

%Vor%

Dann muss jeder, der diese Klasse implementiert, eine Methode bereitstellen, die ein Objekt des Typs des angegebenen Tieres zurückgibt. Also muss Ihr Pretend-Bär Lion returnThis() bereitstellen und wenn er der Dokumentation folgt und diese einfach als return this implementiert, wird das einen Typ-Mismatch Fehler verursachen.

Dies schützt immer noch nicht vor jemandem, der sich bewusst mit Dingen anlegen will und dann new Lion() anstelle von this zurückgibt, aber es wird definitiv Fehler finden, bei denen Sie einfach versucht haben, die Bear extends Animal<Bear> -Klasse zu kopieren Machen Sie die Klasse Grizzly und vergessen Sie, die resultierende Grizzly extends Animal<Bear> in Grizzly extends Animal<Grizzly> zu ändern. (Wenn du Grizzlys wirklich erlauben willst, mit Schwarzbären zusammen zu sein, ist ein weiteres Problem, das das Board deines Zoos entscheiden muss ...)

    
Markus A. 30.11.2012 17:40
quelle

Tags und Links