In Java passiert etwas Merkwürdiges, wenn Sie eine abstrakte Klasse zum Implementieren einer Schnittstelle verwenden: Einige der Methoden der Schnittstelle können vollständig fehlen (dh es ist weder eine abstrakte Deklaration noch eine tatsächliche Implementierung vorhanden), aber der Compiler beschwert sich nicht.
Zum Beispiel angesichts der Schnittstelle:
public interface IAnything {
void m1();
void m2();
void m3();
}
Die folgende abstrakte Klasse wird ohne Warnung oder Fehler fröhlich kompiliert:
public abstract class AbstractThing implements IAnything {
public void m1() {}
public void m3() {}
}
Kannst du erklären warum?
java
interface
abstract-class
Giulio Piancastelli
quelle
quelle
:w
der Dateien.Antworten:
Das liegt daran, dass Sie, wenn eine Klasse abstrakt ist, per Definition Unterklassen davon erstellen müssen, um sie zu instanziieren. Die Unterklassen müssen (vom Compiler) alle Schnittstellenmethoden implementieren, die die abstrakte Klasse ausgelassen hat.
Versuchen Sie nach Ihrem Beispielcode, eine Unterklasse zu erstellen,
AbstractThing
ohne diem2
Methode zu implementieren , und sehen Sie, welche Fehler der Compiler Ihnen gibt. Sie werden gezwungen, diese Methode zu implementieren.quelle
Perfekt in Ordnung.
Sie können abstrakte Klassen nicht instanziieren. Mit abstrakten Klassen können jedoch allgemeine Implementierungen für m1 () und m3 () untergebracht werden.
Also , wenn m2 () Implementierung ist für jede Implementierung aber m1 und m3 ist es nicht. Sie können mit nur der unterschiedlichen m2-Implementierung verschiedene konkrete IAnything-Implementierungen erstellen und von AbstractThing ableiten - unter Berücksichtigung des DRY-Prinzips. Die Überprüfung, ob die Schnittstelle für eine abstrakte Klasse vollständig implementiert ist, ist zwecklos.
Update : Interessanterweise finde ich, dass C # dies als Kompilierungsfehler erzwingt. In diesem Szenario müssen Sie die Methodensignaturen kopieren und ihnen in der abstrakten Basisklasse 'abstract public' voranstellen. (Jeden Tag etwas Neues :)
quelle
Das ist gut. Um das Obige zu verstehen, müssen Sie zuerst die Natur der abstrakten Klassen verstehen. In dieser Hinsicht ähneln sie Schnittstellen. Dies ist , was Oracle sagt über diese hier .
Sie müssen sich also überlegen, was passiert, wenn eine Schnittstelle eine andere Schnittstelle erweitert. Zum Beispiel ...
... wie Sie sehen können, kompiliert dies auch einwandfrei. Einfach, weil eine Schnittstelle genau wie eine abstrakte Klasse NICHT instanziiert werden kann. Es ist daher nicht erforderlich, die Methoden von ihrem "Elternteil" explizit zu erwähnen. ALLE übergeordneten Methodensignaturen werden jedoch implizit Teil der erweiterten Schnittstelle oder der implementierenden abstrakten Klasse. Sobald eine geeignete Klasse (eine, die instanziiert werden kann) das oben Gesagte erweitert, muss sichergestellt werden, dass jede einzelne abstrakte Methode implementiert wird.
Hoffe das hilft ... und Allahu 'alam!
quelle
Schnittstelle bedeutet eine Klasse, die keine Implementierung ihrer Methode hat, sondern nur eine Deklaration.
Andererseits ist eine abstrakte Klasse eine Klasse, die eine Implementierung einer Methode zusammen mit einer Methode mit nur einer Deklaration und keiner Implementierung haben kann.
Wenn wir eine Schnittstelle zu einer abstrakten Klasse implementieren, bedeutet dies, dass die abstrakte Klasse alle Methoden der Schnittstelle geerbt hat. Da es nicht wichtig ist, die gesamte Methode in einer abstrakten Klasse zu implementieren, handelt es sich jedoch um eine abstrakte Klasse (auch durch Vererbung), sodass die abstrakte Klasse einen Teil der Methode ohne Implementierung hier in der Schnittstelle belassen kann. Wenn diese abstrakte Klasse jedoch von einer konkreten Klasse geerbt wird, müssen sie alle diese nicht implementierten Methoden dort in der abstrakten Klasse implementieren.
quelle
Angesichts der Schnittstelle:
So sieht es Java tatsächlich:
Sie können also einige (oder alle) dieser
abstract
Methoden nicht implementieren, so wie Sie es beiabstract
Klassen tun würden, die eine andereabstract
Klasse erweitern.Wenn Sie
implement
eineinterface
, gilt die Regel, dass alleinterface
Methoden in der abgeleiteten implementiert werden müssenclass
, nur für die konkreteclass
Implementierung (dh, die nichtabstract
selbst ist).Wenn Sie tatsächlich vorhaben, ein
abstract class
Out daraus zu erstellen , gibt es keine Regel, die besagt, dass Sieimplement
alleinterface
Methoden anwenden müssen (beachten Sie, dass in einem solchen Fall die Ableitungclass
als deklariert werden mussabstract
).quelle
javap IAnything.class
, um das zweite Code-Snippet zu generieren.Referenz: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
quelle
Abstrakte Klassen sind nicht erforderlich, um die Methoden zu implementieren. Obwohl eine Schnittstelle implementiert wird, können die abstrakten Methoden der Schnittstelle abstrakt bleiben. Wenn Sie versuchen, eine Schnittstelle in einer konkreten Klasse zu implementieren (dh nicht abstrakt) und die abstrakten Methoden nicht implementieren, teilt Ihnen der Compiler Folgendes mit: Implementieren Sie entweder die abstrakten Methoden oder deklarieren Sie die Klasse als abstrakt.
quelle