Java abstrakte Schnittstelle

197

Betrachten Sie ein Beispiel (das in Java kompiliert wird)

public abstract interface Interface {
    public void interfacing();
    public abstract boolean interfacing(boolean really);
}

Warum muss eine Schnittstelle abstrakt "deklariert" werden? Gibt es andere Regeln, die für eine abstrakte Schnittstelle gelten?


Endlich: Wenn abstractes veraltet ist, warum ist es in Java enthalten? Gibt es eine Geschichte für abstrakte Schnittstelle?

Buhake Sindi
quelle
5
Kein Duplikat unter Berücksichtigung des Teils " Endlich: .... ".
Aioobe
Diese verwandte Frage zitiert ein reales Beispiel: stackoverflow.com/questions/4380796/…
Raedwald
1
Und warum fügt Eclipse standardmäßig "abstrakt" hinzu, wenn Sie "Schnittstelle extrahieren"?
ModdyFire
@ModdyFire, bitte näher erläutern?
Buhake Sindi

Antworten:

446

Warum muss eine Schnittstelle abstrakt "deklariert" werden?

Es ist nicht.

public abstract interface Interface {
       \___.__/
           |
           '----> Neither this...

    public void interfacing();
    public abstract boolean interfacing(boolean really);
           \___.__/
               |
               '----> nor this, are necessary.
}

Schnittstellen und ihre Methoden sind implizit abstractund das Hinzufügen dieses Modifikators macht keinen Unterschied.

Gibt es andere Regeln, die für eine abstrakte Schnittstelle gelten?

Nein, es gelten dieselben Regeln. Die Methode muss von jeder (konkreten) implementierenden Klasse implementiert werden.

Wenn Abstract veraltet ist, warum ist es in Java enthalten? Gibt es eine Geschichte für abstrakte Schnittstelle?

Interessante Frage. Ich habe die erste Ausgabe von JLS ausgegraben und selbst dort steht "Dieser Modifikator ist veraltet und sollte nicht in neuen Java-Programmen verwendet werden" .

Okay, noch weiter graben ... Nachdem ich auf zahlreiche defekte Links gestoßen war, gelang es mir, eine Kopie der ursprünglichen Oak 0.2- Spezifikation (oder des "Handbuchs") zu finden. Sehr interessante Lektüre muss ich sagen, und insgesamt nur 38 Seiten! :-)

Unter Abschnitt 5, Schnittstellen, finden Sie das folgende Beispiel:

public interface Storing {
    void freezeDry(Stream s) = 0;
    void reconstitute(Stream s) = 0;
}

Und am Rande steht

In Zukunft wird der Teil "= 0" der Deklarationsmethoden in Schnittstellen möglicherweise nicht mehr angezeigt.

Angenommen, =0durch das abstractSchlüsselwort ersetzt wurde, vermute ich, dass dies abstractirgendwann für Schnittstellenmethoden obligatorisch war!


In Verbindung stehender Artikel: Java: Abstrakte Schnittstellen und abstrakte Schnittstellenmethoden

aioobe
quelle
3
aber abstrakt selbst ist nicht veraltet, oder? Es ist für Schnittstellen veraltet, aber es gibt immer noch abstrakte Klassen und Methoden.
user85421
Danke ;-) Ich denke, ich habe endlich den Ursprung festgenagelt, um überhaupt abstractvor Schnittstellenmethoden zuzulassen .
Aioobe
13
Beeindruckend. Es ist also "von Natur aus" veraltet. Diese JLS-Designer hatten wirklich immer solche Angst, etwas zu zerbrechen, sogar Dinge zu zerbrechen, die nie veröffentlicht wurden ... :-)
Lukas Eder
@ Aioobe, Sie müssen der Google Web Crawler sein, von dem wir nichts wissen ... lol
Buhake Sindi
18
Übrigens. "public" ist auch für Methoden in einer Schnittstellendeklaration nicht erforderlich ... sie sind immer öffentlich.
Rec
37

Es ist nicht notwendig, es ist optional, genau wie publicbei Schnittstellenmethoden.

Siehe die JLS dazu:

http://java.sun.com/docs/books/jls/second_edition/html/interfaces.doc.html

9.1.1.1 abstrakte Schnittstellen Jede Schnittstelle ist implizit abstrakt. Dieser Modifikator ist veraltet und sollte nicht in neuen Programmen verwendet werden.

Und

9.4 Abstrakte Methodenerklärungen

[...]

Aus Gründen der Kompatibilität mit älteren Versionen der Java-Plattform ist es zulässig, den abstrakten Modifikator für in Schnittstellen deklarierte Methoden redundant anzugeben.

Es ist erlaubt, aber aus Stilgründen wird dringend davon abgeraten, den öffentlichen Modifikator für Schnittstellenmethoden redundant anzugeben.

Lukas Eder
quelle
7
an JLS: Es ist erlaubt, aber aus Stilgründen wird dringend davon abgeraten, zwei Sätze mit derselben Bedeutung und fast genauem Wortlaut redundant nebeneinander zu schreiben ...
n611x007
11

Es ist nicht erforderlich, die Schnittstelle abstrakt zu deklarieren.

Genau wie das Deklarieren all dieser Methoden als öffentlich (was sie bereits sind, wenn die Schnittstelle öffentlich ist) oder abstrakt (was sie bereits in einer Schnittstelle sind) ist redundant.

Niemand hält dich jedoch auf.

Andere Dinge, die Sie explizit angeben können, aber nicht müssen:

  • Rufen Sie super () in der ersten Zeile eines Konstruktors auf
  • extends Object
  • vererbte Schnittstellen implementieren

Gibt es andere Regeln, die für eine abstrakte Schnittstelle gelten?

Eine Schnittstelle ist bereits "abstrakt". Das erneute Anwenden dieses Schlüsselworts macht absolut keinen Unterschied.

Thilo
quelle
2
Anscheinend sind die Methoden sogar öffentlich, wenn die Schnittstelle selbst paketprivat ist.
Thilo
7

Seien Sie sich bewusst, dass es im Frühling keine akademische Bedeutung hat. Die abstrakte Oberfläche ist eine Warnung an den Entwickler, sie nicht zu verwenden @Autowired. Ich hoffe, dass Spring / Eclipse @Autowireddieses Attribut betrachtet und vor dessen Verwendung warnt / scheitert.

Ein echtes Beispiel: @Service-Proxy unter @Transnational zu einem @Repository müssen dieselben grundlegenden Methoden verwenden, sie sollten jedoch unterschiedliche Schnittstellen verwenden, die diese abstrakte Schnittstelle aufgrund von erweitern @Autowired. (Ich nenne das XXXSpec-Schnittstelle)

Adi Lev
quelle
+1 guter Treffer, ich suchte breit nach einer Trennung von nicht passivierbaren Sessionbean-Injektionen. Vielleicht kann ich Findbugs / Checkstyle für eine Regel verwenden ...
Grim
3

Jede Schnittstelle ist implizit abstrakt.
Dieser Modifikator ist veraltet und sollte nicht in neuen Programmen verwendet werden.

[Die Java-Sprachspezifikation - 9.1.1.1 abstractSchnittstellen]

Beachten Sie auch, dass die Methoden der Schnittstellenmitglieder implizit sind public abstract.
[Die Java-Sprachspezifikation - 9.2 Schnittstellenmitglieder]

Warum sind diese Modifikatoren implizit? Es gibt keinen anderen Modifikator (nicht einmal den Modifikator ' kein Modifikator '), der hier nützlich wäre, sodass Sie ihn nicht explizit eingeben müssen.

Kapex
quelle
2

Es ist nicht notwendig. Es ist eine Eigenart der Sprache.

Böhmisch
quelle
2

Dies ist nicht erforderlich, da Schnittstellen standardmäßig abstrakt sind, da alle Methoden in einer Schnittstelle abstrakt sind.

Swagatika
quelle
-2

Eine abstrakte Schnittstelle ist zumindest theoretisch nicht so überflüssig, wie jeder zu sagen scheint.

Eine Schnittstelle kann ebenso wie eine Klasse erweitert werden. Wenn Sie eine Schnittstellenhierarchie für Ihre Anwendung entwerfen, verfügen Sie möglicherweise über eine Basisschnittstelle. Sie erweitern andere Schnittstellen von, möchten diese jedoch nicht als Objekt an sich.

Beispiel:

public abstract interface MyBaseInterface {
    public String getName();
}

public interface MyBoat extends MyBaseInterface {
    public String getMastSize();
}

public interface MyDog extends MyBaseInterface {
    public long tinsOfFoodPerDay();
}

Sie möchten nicht, dass eine Klasse das MyBaseInterface implementiert, sondern nur die beiden anderen, MMyDog und MyBoat, aber beide Schnittstellen teilen sich die MyBaseInterface-Schnittstelle, haben also eine 'name'-Eigenschaft.

Ich weiß, dass es ein bisschen akademisch ist, aber ich dachte, einige könnten es interessant finden. :-)

In diesem Fall ist es wirklich nur ein "Marker", um den Implementierern der Schnittstelle zu signalisieren, dass sie nicht für die eigenständige Implementierung ausgelegt ist. Ich sollte darauf hinweisen, dass ein Compiler (zumindest die sun / ora 1.6, mit der ich es versucht habe) eine Klasse kompiliert, die eine abstrakte Schnittstelle implementiert.

Eurospoofer
quelle
3
Ich glaube, Sie haben meine Frage absolut falsch verstanden.
Buhake Sindi
3
Ich stimme dieser Argumentation nicht zu. Ich denke, jede Schnittstelle muss einen vollständig nutzbaren Funktionsumfang bieten, und daher kann jede Schnittstelle für sich implementiert werden. Es gibt auch keinen Grund für einen Compiler, sich zu weigern, eine Klasse zu kompilieren, die eine explizit als abstrakt deklarierte Schnittstelle implementiert, da alle Schnittstellen bereits implizit abstrakt sind. Dies würde die Bedeutung des Schlüsselworts "abstrakt" vollständig ändern.
BladeCoder
-3

Nun, 'Abstract Interface' ist ein lexikalisches Konstrukt: http://en.wikipedia.org/wiki/Lexical_analysis .

Es wird vom Compiler benötigt, man kann auch schreiben interface.

Lassen Sie sich nicht zu sehr auf das lexikalische Konstrukt der Sprache ein, da sie es möglicherweise dort abgelegt haben, um eine Mehrdeutigkeit der Kompilierung zu beheben, die während des Kompilierungsprozesses als Sonderfälle bezeichnet wird, oder um eine gewisse Abwärtskompatibilität zu erzielen. Versuchen Sie, sich auf das lexikalische Kernkonstrukt zu konzentrieren.

Die Essenz von `interface besteht darin, ein abstraktes Konzept (Idee / Denken / Denken höherer Ordnung usw.) zu erfassen, dessen Implementierung variieren kann ... das heißt, es kann mehrere Implementierungen geben.

Eine Schnittstelle ist ein reiner abstrakter Datentyp, der die Merkmale des Objekts darstellt, das erfasst oder dargestellt wird.

Merkmale können durch Raum oder Zeit dargestellt werden. Wenn sie durch Leerzeichen (Speicher) dargestellt werden, bedeutet dies, dass Ihre konkrete Klasse ein Feld und eine Methode / Methoden implementiert, die auf diesem Feld oder nach Zeit arbeiten, was bedeutet, dass die Aufgabe der Implementierung des Features rein rechnerisch ist (erfordert mehr CPU-Uhren für die Verarbeitung), so dass Sie einen Kompromiss zwischen Raum und Zeit für die Implementierung von Features haben.

Wenn Ihre konkrete Klasse nicht alle Funktionen implementiert, wird sie wieder abstrakt, weil Sie eine Implementierung Ihres Gedankens oder Ihrer Idee oder Abstraktheit haben, diese jedoch nicht vollständig ist. Sie geben sie nach abstractKlasse an.

Eine konkrete Klasse ist eine Klasse / Gruppe von Klassen, die die Abstraktheit, die Sie versuchen, die Klasse XYZ zu erfassen, vollständig erfasst.

So ist das Muster

Interface--->Abstract class/Abstract classes(depends)-->Concrete class
Manish
quelle
1
Diese Antwort beantwortet meine Frage überhaupt nicht. Auch "It seams like you are new to Java. "Ja wirklich?"
Buhake Sindi
"Zusammenfassung ist veraltet"
Manish
(1) "abstract is obsolet" -> Wenn sie es entfernen und der Compiler es nicht mehr erkennt, wird die vorherige Version des Quellcodes mit "abstract interface" nicht in einer neueren Version kompiliert. Sie müssen die Abwärtskompatibilität beibehalten. Wenn Sie eine abstrakte Schnittstelle definieren, bleibt die Bedeutung des Schlüsselworts interface zusammen mit der Zusammenfassung "abstrakt" erhalten. Dies ist eine viel sauberere Version. Für erfahrene Programmierer wie Sie wurde jedoch die Verknüpfung "Schnittstelle" bereitgestellt. Ihre Frage ähnelt i = i + 1 == > i ++ .. Wahl liegt bei Ihnen, was Sie wählen: D
Manish
Schauen Sie sich die akzeptierte Antwort an. Ich weiß, dass die abstractBenutzeroberfläche veraltet ist. Ich wollte wissen, warum es immer noch akzeptabel ist und welche Geschichte hinter der abstractBenutzeroberfläche steckt . Sie geben mir einen Java 101-Leitfaden zu Abstract vs Interface.
Buhake Sindi
Es ist kein lexikalisches Konstrukt. Es ist Syntax. Semantisch ist es redundant. Es ist nicht "vom Compiler erforderlich". Der Teil über Raum / Zeit ist nur Trottel. Keiner dieser Unsinn beantwortet die gestellte Frage. Verwenden Sie keine Code-Formatierung für Text, der kein Code ist.
Marquis von Lorne