Können überschriebene Methoden unterschiedliche Rückgabetypen haben ?
java
methods
overriding
Santidoo
quelle
quelle
error: method() in subclass cannot override method() in superclass
Antworten:
Java unterstützt * kovariante Rückgabetypen für überschriebene Methoden. Dies bedeutet eine überschriebene Methode einen hat mehr spezifischen Rückgabetyp. Das heißt, solange der neue Rückgabetyp dem Rückgabetyp der Methode zugeordnet ist, die Sie überschreiben, ist dies zulässig.
Beispielsweise:
Dies ist in Abschnitt 8.4.5 der Java-Sprachspezifikation angegeben :
("| R2 |" bezieht sich auf das Löschen von R2 gemäß Definition in §4.6 des JLS .)
* Vor Java 5 hatte Java invariante Rückgabetypen, was bedeutete, dass der Rückgabetyp einer Methodenüberschreibung erforderlich war, um genau mit der überschriebenen Methode übereinzustimmen.
quelle
Ja, es kann abweichen, aber es gibt einige Einschränkungen.
Vor Java 5.0 müssen beim Überschreiben einer Methode sowohl die Parameter als auch der Rückgabetyp genau übereinstimmen. In Java 5.0 wird eine neue Funktion namens kovarianter Rückgabetyp eingeführt. Sie können eine Methode mit derselben Signatur überschreiben, aber eine Unterklasse des zurückgegebenen Objekts zurückgeben. Mit anderen Worten, eine Methode in einer Unterklasse kann ein Objekt zurückgeben, dessen Typ eine Unterklasse des Typs ist, der von der Methode mit derselben Signatur in der Oberklasse zurückgegeben wird.
quelle
Ja, wenn sie einen Subtyp zurückgeben. Hier ist ein Beispiel:
Dieser Code wird kompiliert und ausgeführt.
quelle
Im Großen und Ganzen kann die Art der überschreibenden Methode "Ja" unterschiedlich sein. Aber es ist nicht einfach, da es einige Fälle gibt, die damit zusammenhängen.
Fall 1: Wenn der Rückgabetyp ein primitiver Datentyp oder eine Leere ist.
Ausgabe: Wenn der Rückgabetyp ungültig oder primitiv ist, sollten der Datentyp der übergeordneten Klassenmethode und der überschreibenden Methode identisch sein. Wenn der Rückgabetyp beispielsweise int, float, string ist, sollte er identisch sein
Fall 2: Wenn der Rückgabetyp vom Datentyp abgeleitet ist:
Ausgabe: Wenn der Rückgabetyp der übergeordneten Klassenmethode vom abgeleiteten Datentyp ist, ist der Rückgabetyp der überschreibenden Methode der gleiche abgeleitete Datentyp der Unterklasse wie der abgeleitete Datentyp. Angenommen, ich habe eine Klasse A, B ist eine Unterklasse von A, C ist eine Unterklasse von B und D ist eine Unterklasse von C; Wenn dann die Superklasse Typ A zurückgibt, kann die überschreibende Methode Unterklasse A, B, C oder D zurückgeben, dh ihre Untertypen. Dies wird auch als Kovarianz bezeichnet.
quelle
Ja Es ist möglich, dass der Rückgabetyp nur dann unterschiedlich sein kann, wenn der Rückgabetyp der übergeordneten Klassenmethode
ein Supertyp des Rückgabetyps der untergeordneten Klassenmethode
ist
Wenn dies der andere Rückgabetyp ist, kann er zugelassen werden ...
quelle
Nun, die Antwort ist ja ... und nein.
hängt von der Frage ab. Alle hier antworteten in Bezug auf Java> = 5, und einige erwähnten, dass Java <5 keine kovarianten Rückgabetypen enthält.
Die Java-Sprachspezifikation> = 5 unterstützt dies tatsächlich, die Java-Laufzeit jedoch nicht. Insbesondere wurde die JVM nicht aktualisiert, um kovariante Rückgabetypen zu unterstützen.
Java 5 implementierte eine Reihe neuer Sprachfunktionen, ohne die JVM oder die Klassendateispezifikation zu ändern. Stattdessen wurden alle Funktionen mit Tricks in Javac implementiert: Der Compiler generiert / verwendet einfache Klassen für verschachtelte / innere Klassen, Typlöschung und Casts für Generika, synthetische Accessoren für verschachtelte / innere Klassen, private "Freundschaft", synthetische Instanzfelder für äußere "dies". Zeiger, synthetische statische Felder für '.class'-Literale usw. usw.
und kovariante Rückgabetypen sind noch mehr syntaktischer Zucker, der von Javac hinzugefügt wird.
Zum Beispiel beim Kompilieren:
javac gibt zwei get-Methoden in der Derived-Klasse aus:
Die generierte Bridge-Methode (markiert
synthetic
undbridge
in Bytecode) wird tatsächlich überschrieben,Object:Base:get()
da für die JVM Methoden mit unterschiedlichen Rückgabetypen völlig unabhängig sind und sich nicht gegenseitig überschreiben können. Um das erwartete Verhalten zu erzielen, ruft die Bridge einfach Ihre "echte" Methode auf. Im obigen Beispiel kommentiert javac sowohl Bridge- als auch Real-Methoden in Derived mit @SomeAnnotation.Beachten Sie, dass Sie diese Lösung in Java <5 nicht manuell codieren können, da sich Bridge- und Real-Methoden nur im Rückgabetyp unterscheiden und daher in einem Java-Programm nicht koexistieren können. In der JVM-Welt sind Methodenrückgabetypen (genau wie ihre Argumente) Teil der Methodensignatur. Daher werden die beiden Methoden mit demselben Namen und denselben Argumenten von der JVM aufgrund ihrer unterschiedlichen Rückgabetypen als völlig unabhängig angesehen. und kann koexistieren.
(Übrigens sind die Feldtypen in ähnlicher Weise Teil der Feldsignatur im Bytecode, daher ist es legal, mehrere Felder unterschiedlichen Typs zu haben, die jedoch innerhalb einer einzelnen Bytecode-Klasse gleich benannt sind.)
Um Ihre Frage vollständig zu beantworten: Die JVM unterstützt keine kovarianten Rückgabetypen, aber javac> = 5 fälscht sie zur Kompilierungszeit mit einer Beschichtung aus süßem syntaktischem Zucker.
quelle
Überschreiben und Zurückgeben von Typen sowie kovariante Rückgaben
Die Unterklasse muss eine Methode definieren, die genau mit der geerbten Version übereinstimmt. Ab Java 5 können Sie den Rückgabetyp in der ändern
Beispielcode
Java 5 wird dieser Code kompiliert. Wenn Sie versuchen, diesen Code mit einem 1.4-Compiler zu kompilieren, wird der Versuch angezeigt, einen inkompatiblen Rückgabetyp zu verwenden - sandeep1987 vor 1 Minute
quelle
Die anderen Antworten sind alle richtig, aber überraschenderweise lassen sie hier alle den theoretischen Aspekt aus: Rückgabetypen können unterschiedlich sein, aber sie können den in der Superklasse verwendeten Typ aufgrund des Liskov-Substitutionsprinzips nur einschränken .
Es ist ganz einfach: Wenn Sie einen "Client" -Code haben, der eine Methode aufruft:
dann muss das oben genannte funktionieren (und etwas zurückgeben, das
int
unabhängig von der Implementierung istbar()
ist, aufgerufen wird).Bedeutung: Wenn es eine Balkenunterklasse gibt, die überschreibt
bar()
Sie immer noch etwas zurückgeben, das den "Anrufercode" nicht beschädigt.Mit anderen Worten: Nehmen Sie an, dass die Basis
bar()
int zurückgeben soll. Dann könnte eine Unterklasse zurückkehrenshort
- aber nicht,long
weil Anrufer mit einemshort
Wert gut umgehen können, aber nicht mit einemlong
!quelle
Der Rückgabetyp muss mit dem Rückgabetyp oder einem Untertyp des Rückgabetyps identisch sein, der in der ursprünglich überschriebenen Methode in der Oberklasse deklariert wurde.
quelle
JA, es kann möglich sein
quelle
Ja. Es ist möglich, dass überschriebene Methoden unterschiedliche Rückgabetypen haben.
Die Einschränkungen bestehen jedoch darin, dass die überschriebene Methode einen Rückgabetyp haben muss, der spezifischer vom Rückgabetyp der tatsächlichen Methode ist.
Alle Antworten enthalten Beispiele für die überschriebene Methode mit einem Rückgabetyp, der eine Unterklasse des Rückgabetyps der tatsächlichen Methode ist.
Zum Beispiel :
Dies ist jedoch nicht nur auf die Unterklasse beschränkt. Selbst Klassen, die eine Schnittstelle implementieren, sind ein bestimmter Typ der Schnittstelle und können daher ein Rückgabetyp sein, bei dem die Schnittstelle erwartet wird.
Zum Beispiel :
quelle
quelle