Ich lese das unglaubliche Buch "Ein Leitfaden für Programmierer zur Java-Scjp-Zertifizierung" für jdk6 und einen Abschnitt über generisches Überschreiben. Darauf wird Subsignature und Override-Equivalent beschrieben und einige Beispiele von Override-Äquivalenten beschrieben, die ich zitiere:
Gegeben die folgenden drei generischen Methodendeklarationen in einer Klasse:
static <T> void merge (MyStack<T> s1, MyStack<T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? extends T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? super T> s2) { /*...*/ }
Nach dem Löschen lautet die Signatur aller drei Methoden:
merge(MyStack, MyStack)
d. h. die Signaturen der Methoden sind override-äquivalent, daher diese Methoden sind nicht überlastet.
Ich stimme nicht völlig zu, dass diese Methoden override-äquivalent sind, tatsächlich denke ich, dass die Methoden einen "Namen durch Löschung" haben, aber keiner ist Subsignatur des anderen ... vielleicht bin ich falsch, also möchte ich etwas Licht dazu haben.
Die Definitionen der Untersignatur lassen mich denken, dass sie keine Untersignaturen zwischen ihnen sind.
In JSL 6 # 8.4.2 Methodensignatur ( Ссылка )
Zwei Methoden haben die gleiche Signatur, wenn sie denselben Namen und dieselben Argumenttypen haben. Zwei Methoden- oder Konstruktordeklarationen M und N haben die gleichen Argumenttypen, wenn alle folgenden Bedingungen zutreffen:
Sie. haben die gleiche Anzahl von formalen Parametern (möglicherweise Null)
Sie haben die gleiche Anzahl von Typparametern (möglicherweise Null)
Lassen Sie
<A1,...,An>
die formalen Typparameter von M sein und lassen Sie<B1,...,Bn>
die formalen Typparameter von N. sein. Nach dem Umbenennen jedes Auftretens eines Bi in Ns Typ zu Ai die Grenzen der entsprechenden Typvariablen und der Argumenttypen von M und N sind gleich.Die Signatur einer Methode m1 ist eine Untersignatur der Signatur einer Methode m2, wenn eine der Methoden vorhanden ist m2 hat die gleiche Signatur wie m1 oder die Signatur von m1 ist die gleiche wie die Löschung der Signatur von m2
...
Zwei Methodensignaturen m1 und m2 sind override-äquivalent, wenn entweder m1 eine Untersignatur von m2 oder m2 eine Untersignatur von m1 ist.
In JSL 8 # 8.4.2. Methodensignatur ( Ссылка )
Zwei Methoden oder Konstruktoren, M und N, haben die gleiche Signatur, wenn sie den gleichen Namen, die gleichen Typparameter (falls vorhanden) haben (§ 8.4.4), und, nach der Anpassung der formalen Parametertypen von N an die die Typparameter von M, die gleichen formalen Parametertypen.
Die Signatur einer Methode m1 ist eine Untersignatur der Signatur einer Methode m2, wenn entweder:
m2 hat dieselbe Signatur wie m1 oder
Die Signatur von m1 ist die gleiche wie die Löschung der Signatur von m2.
Zwei Methodensignaturen m1 und m2 sind override-äquivalent, wenn entweder m1 eine Untersignatur von m2 oder m2 eine Untersignatur von m1 ist.
Um es einfach zu sagen, mein Zweifel ist, dass ich das aus der Subsignaturdefinition in Bezug auf die Löschung verstehe "Eine Unterschrift ohne Löschung ist gleich der Löschung von der anderen Unterschrift" .. und nicht dass "beide Signaturen nach dem Löschen gleich sind" .. es ist subtil aber wichtig (Übrigens, die override-äquivalente Definition basiert auf Subsignaturdefinition, deshalb frage ich nach Untersignaturen)
Der Wortlaut des Buches passt meiner Meinung nach hier nicht besonders gut zusammen. Überladen wird in Form einer Negation der Override-Äquivalenz definiert, wie in JLS (8.4.9) (Paraphrasierung: Wenn zwei Methoden mit demselben Namen existieren, aber keine Override-Äquivalente sind, werden sie überladen).
Aber das angegebene Beispiel ist eines, bei dem die Methoden NICHT override-äquivalent sind, aber DO verursachen a Kompilierzeitfehler aus anderen Gründen (Namenskonflikt - ein bestimmter Kompilierzeitfehler, der in JLS 8.4.8.3 ) und deshalb nicht überladen.
Wie ich es verstehe, werfen Sie eine Frage über die genaue Semantik dieser Satzklausel auf:
"... oder die Signatur von m1 ist die gleiche wie die Löschung der Signatur von m2"
In Kombination mit
m1 und m2 sind override-äquivalent, wenn entweder m1 eine Untersignatur von m2 oder m2 eine Untersignatur von m1 ist.
Ihr Buch impliziert, dass dies als
interpretiert werden sollte"oder das Löschen der Signatur von m1 ist das gleiche wie das Löschen der Signatur von m2"
(hinzugefügte Wörter fett und kursiv).
Während Sie es als
interpretieren würden"oder die Signatur von m1 ( ohne Löschen ) ist dasselbe wie das Löschen der Signatur von m2"
Ihre Interpretation ist richtig. Ich denke nicht, dass der Satz mehrdeutig ist, deshalb denke ich, dass ich ihn auf die erste Art interpretiere (dh dass die Löschung der beiden Signaturen ist identisch) ist falsch. Vielleicht möchten Sie diese verwandte Antwort betrachten, um meiner Meinung hier Gewicht zu verleihen (ich habe es gefunden, weil ich meine Frage überprüfen wollte) Verständnis auch).
Der Abschnitt des Buches, den du zitierst, versucht tatsächlich, das Überladen zu beschreiben.
Nun - wenn Sie über Überlastung nachdenken - die JLS (8.4.9) sagt: dass:
Wenn zwei Methoden einer Klasse (ob beide in derselben Klasse deklariert sind oder beide von einer Klasse geerbt oder deklariert und geerbt sind) denselben Namen haben, aber Signaturen, die nicht override-äquivalent sind, lautet der Methodenname soll überlastet sein.
Dies war seit mindestens Java 6 konsistent. Hier kommt die Verbindung zwischen override-equivalent
und dem Überladen her.
OK - Ihre Methoden würden also überladen, weil sie nicht streng override-äquivalent sind. Richtig?
Falsch.
Weil genau über diesem Abschnitt in 8.4.8.3 , die JLS fügt einen spezifischen Kompilierzeitfehler ein:
Es ist ein Fehler bei der Kompilierung, wenn eine Typdeklaration T eine Member-Methode m1 hat und eine in T deklarierte Methode oder ein Supertyp von T existiert, so dass alle folgenden Aussagen zutreffen:
m1 und m2 haben denselben Namen.
m2 ist von T zugänglich.
Die Signatur von m1 ist keine Subsignatur (§8.4.2) der Signatur von m2.
Die Signatur von m1 oder einer Methode m1 überschreibt (direkt oder indirekt) das gleiche Löschen wie die Signatur von m2 oder einige Methoden m2-Überschreibungen (direkt oder indirekt).
Dies ist das Szenario in Ihrem Beispiel. Direkt unter diesem Abschnitt erklärt es, warum es notwendig ist:
Diese Einschränkungen sind notwendig, da Generika durch Löschen implementiert werden. Die obige Regel bedeutet, dass Methoden, die in derselben Klasse mit demselben Namen deklariert sind, unterschiedliche Löschungen haben müssen. Es impliziert auch, dass eine Typdeklaration zwei unterschiedliche Aufrufe derselben generischen Schnittstelle nicht implementieren oder erweitern kann.
Das Beispiel in diesem Buch ist ein seltsames Beispiel, da Java das Überschreiben von statischen Methoden nicht zulassen würde (die Signatur einer Methode in einer Unterklasse könnte das in der Oberklasse verbergen). Das macht das Konzept, nicht übersteuert-Äquivalent für einen Lernenden aus meiner Sicht ein wenig schwierig. Sie können jedoch static
entfernen und trotzdem den Effekt sehen, den sie demonstrieren möchten.