2011-01-14 9 views
4

In Java definieren Leute oft eine Schnittstelle zusammen mit einer Klasse und verwenden Schnittstellennamen anstelle von Klassennamen, um spätere Implementierungen zu ermöglichen. Hier wird die logische Schnittstelle dupliziert.Warum kann ich "implementiert AClass" in Java nicht schreiben?

Diese Art der "Nur-für-Fall" -Duplizierung wäre nicht notwendig, wenn Java die Verwendung einer Klasse als Schnittstelle zulässt, zB: class MyScanner extends MyStuff implements java.util.Scanner. Auch würde dies die Situation erleichtern, in der ich einen Klassentyp bereitstellen muss, aber ich möchte diese Klasse nicht erweitern.

Wie ich verstehe, „eine Klasse Umsetzung“ würde abgelehnt werden, nicht nur durch den Compiler, sondern auch von der JVM (wenn ich diese Erklärung in Klassendatei gehackt). Gibt es dafür technische Schwierigkeiten oder wird das nicht als wichtig angesehen? Es sieht nicht wie ein Rückwärtskompatibilitäts-Problem aus (ich meine, alter Code lief gut, wenn JVM dies unterstützte).

EDIT: zur Klarstellung, werde ich hier kopieren StriplingWarrior ist viel besser Wortlaut der gleichen Fragen:

Warum kann eine Klasse "nicht implementieren" Methode einer anderen Klasse, ohne diese Klasse tatsächlich zu erweitern? Ist es ein technisches Problem? Würde es uns irgendwie für einige Probleme öffnen, die das OP nicht vorhersehen kann?

+0

Es klingt nicht wie Sie eine Frage haben. Wenn Sie einen Vorschlag für eine Spracherweiterung haben, ist dies wirklich nicht der richtige Ort. –

+3

gut, schauen Sie sorgfältig Konstantin, oder suchen Sie nach einem Fragezeichen :) – Aivar

+2

@Konstantin Komissarchik: Ich stimme nicht zu. Ich denke, dies ist eine gut durchdachte Frage: Warum kann eine Klasse den Methodenvertrag einer anderen Klasse nicht "implementieren", ohne diese Klasse tatsächlich zu erweitern? Ist es ein technisches Problem? Würde es uns irgendwie für einige Probleme öffnen, die das OP nicht vorhersehen kann? Ich denke, es zählt als Programmierfrage. – StriplingWarrior

Antwort

9

Verdeute ich richtig, dass MyClass implements AClass bedeuten würde, dass MyClass Implementierungen für alle öffentlichen Methoden, die AClass hat, bereitstellen muss (oder erben)? I.e. jede Klasse definiert implizit eine Schnittstelle, die aus ihren öffentlichen Methoden besteht?

Wenn ja, dann ist das Problem, das ich mit, dass zu sehen ist, dass Schnittstellen sind wirklich etwas ganz anderes, Klassen und die beiden sollten nicht so gemischt werden. Schnittstellen definieren einen Vertrag, klassen eine Implementierung. Eine Konsequenz daraus: Die Funktionalität von Klassen kann relativ frei erweitert werden, nicht jedoch Schnittstellen zu bestehenden Implementierungen.

So haben Sie einen sehr konkreten Grund, warum Ihr Vorschlag schlecht wäre: Sie könnten nie eine öffentliche Methode zu einer Klasse hinzufügen, ohne zu riskieren, Code zu brechen, der implements dieser Klasse.

Und auf der anderen Seite, welche Probleme würde es lösen? Die Code-Duplizierung, wenn Sie eine Schnittstelle mit einer einzelnen Implementierung haben? Wie wäre es, das zu lösen, indem Sie es nicht tun? IMO ist es normalerweise etwas, das von Leuten getan wird, die TDD dogmatisch machen, während sie veraltete Spott-Frameworks verwenden, die nicht in der Lage sind, konkrete Klassen zu verspotten.

+0

hmm, guter Punkt! – Aivar

+1

Punkt in Fettschrift ist sehr solide. (+1) –

5

Das Problem ist multiple inheritance. Wenn Sie versuchen, zwei Klassen zu erweitern oder zu implementieren, gibt es potenzielle semantische Probleme.

Sie können mehrere Schnittstellen implementieren und von einer Klasse aus erweitern. Sie können jedoch nur Schnittstellen implementieren, die die meisten Probleme mit der Mehrfachvererbung umgehen, indem Sie einfach die Spezifikation als deklarativ erzwingen, sodass der Implementierer die Methoden direkt implementieren muss. In diesem Fall werden Methodenkonflikte gelöst, indem einfach eine Methode implementiert und für beide Schnittstellen gezählt wird.

+0

Ich hatte den Eindruck, dass das OP gefragt hat, warum man die String-Schnittstelle nicht implementieren kann, obwohl es keine explizite Schnittstelle definiert hat. Ist das richtig, OP? –

+0

Eigentlich möchte ich nicht die Implementierung von dieser Klasse, nur es ist Typ (es ist "logische" Schnittstelle). Ich werde meine Frage klären. – Aivar

+0

Nun, in diesem Fall läuft es nur darauf hinaus, "so funktioniert Java". Und viele populäre objektorientierte Sprachen tun das. Wenn Sie etwas anderes möchten, kann ich Go empfehlen? Go ist eine Sprache, die Schnittstellen hat (und nicht unbedingt reale Klassen); Sie implementieren automatisch eine Schnittstelle, indem Sie einfach die richtigen Methoden definieren. Es gibt viele Ein-oder Null-Methoden-Schnittstellen. Vielleicht möchten Sie auch eine funktionale Programmiersprache ausprobieren. –

1

Wie bereits erwähnt wurde, ist dies, wie der Standard definiert ist und nicht Teil des Entscheidungsprozesses zu sein ich nur Chip mit meinem $ 0,02 kann. Diese

ist nicht so viel über doppelte logische Schnittstellen, sondern ein Standard für die Erstellung einer API, die Sie flexibel sein möchten. Es wird als gute Entwurfspraxis angesehen, selbst in Sprachen, die die Mehrfachvererbung unterstützen, Schnittstellen von einer API bereitzustellen.

Angesichts des aktuellen Status der IDEs ist es ziemlich einfach, dies nicht im Voraus zu tun und dann später umzuformen, wenn Sie entscheiden, dass Sie mehrere Implementierungen eines bestimmten Typs benötigen.

Es kann auch Anwendungsfälle dagegen geben, bei denen innerhalb Ihres Codes eine starke Abhängigkeit von der Funktionalität einer Klasse besteht und durch eine andere Implementierung Ihr Code beschädigt werden könnte. Dies ist der Punkt, von dem zu tun in der Lage:

ClassA a = new ClassA(); 

statt

InterfaceA a = new ClassA(); 

zu unerwartetem Verhalten Dies kann führen.

+0

Macht Sinn, danke! – Aivar

Verwandte Themen