920 Stimmen

Was bedeutet es, "auf eine Schnittstelle zu programmieren"?

Ich habe das schon ein paar Mal gehört und weiß nicht, was es bedeutet. Wann und warum sollten Sie dies tun?

Ich weiß, was Schnittstellen bewirken, aber die Tatsache, dass ich mir darüber nicht im Klaren bin, lässt mich glauben, dass ich sie nicht richtig nutze.

Ist es einfach so, wenn Sie das tun würden:

IInterface classRef = new ObjectWhatever()

Sie können jede Klasse verwenden, die IInterface ? Wann sollten Sie das tun? Das Einzige, was mir einfällt, ist, wenn Sie eine Methode haben und sich nicht sicher sind, welches Objekt außer der Implementierung der Methode übergeben werden soll. IInterface . Ich kann mir nicht vorstellen, wie oft Sie das tun müssen.

Und wie kann man eine Methode schreiben, die ein Objekt aufnimmt, das eine Schnittstelle implementiert? Ist das möglich?

4 Stimmen

Wenn Sie sich daran erinnern können und Ihr Programm optimal sein soll, können Sie kurz vor der Kompilierung die Schnittstellendeklaration gegen die tatsächliche Implementierung austauschen. Die Verwendung einer Schnittstelle fügt eine Ebene der Indirektion hinzu, die zu Leistungseinbußen führt. Verteilen Sie Ihren auf Schnittstellen programmierten Code jedoch...

25 Stimmen

@Ande Turner: Das ist ein schlechter Ratschlag. 1). "Ihr Programm muss optimal sein" ist kein guter Grund für das Auslagern von Schnittstellen! Dann sagen Sie: "Verteilen Sie Ihren programmierten Code trotzdem auf Schnittstellen..." Sie raten also, dass Sie bei Anforderung (1) dann suboptimalen Code veröffentlichen?!?

82 Stimmen

Die meisten der Antworten hier sind nicht ganz richtig. Es bedeutet nicht oder impliziert nicht einmal "das Schlüsselwort interface verwenden". Eine Schnittstelle ist eine Spezifikation, wie etwas zu verwenden ist - gleichbedeutend mit dem Vertrag (schlagen Sie es nach). Getrennt davon ist die Implementierung, die besagt, wie der Vertrag erfüllt wird. Programmieren Sie nur gegen die Garantien der Methode/des Typs, so dass, wenn die Methode/der Typ auf eine Weise geändert wird, die immer noch dem Vertrag entspricht, der Code, der sie verwendet, nicht kaputt geht.

3voto

Damien Punkte 13547

Der Vorteil einer Schnittstelle ist also, dass ich den Aufruf einer Methode von einer bestimmten Klasse trennen kann. Stattdessen erstelle ich eine Instanz der Schnittstelle, deren Implementierung von einer beliebigen Klasse übernommen wird, die diese Schnittstelle implementiert. So kann ich viele Klassen haben, die ähnliche, aber leicht unterschiedliche Funktionen haben, und in einigen Fällen (die Fälle, die mit der Absicht der Schnittstelle zusammenhängen) ist es egal, um welches Objekt es sich handelt.

Ich könnte zum Beispiel eine Bewegungsschnittstelle haben. Eine Methode, die etwas "bewegen" lässt, und jedes Objekt (Person, Auto, Katze), das die Bewegungsschnittstelle implementiert, könnte übergeben und angewiesen werden, sich zu bewegen. Ohne dass die Methode weiß, um welche Art von Klasse es sich handelt.

3voto

RogerV Punkte 3726

In Java implementieren diese konkreten Klassen alle die Schnittstelle CharSequence:

CharBuffer, String, StringBuffer, StringBuilder

Diese konkreten Klassen haben keine andere gemeinsame Elternklasse als Object, so dass es nichts gibt, was sie miteinander verbindet, außer der Tatsache, dass sie alle etwas mit Arrays von Zeichen zu tun haben, diese darstellen oder manipulieren. So können beispielsweise die Zeichen von String nicht mehr geändert werden, sobald ein String-Objekt instanziiert ist, während die Zeichen von StringBuffer oder StringBuilder bearbeitet werden können.

Jede dieser Klassen ist jedoch in der Lage, die Methoden der CharSequence-Schnittstelle in geeigneter Weise zu implementieren:

char charAt(int index)
int length()
CharSequence subSequence(int start, int end)
String toString()

In einigen Fällen wurden Java-Klassenbibliotheksklassen, die früher String akzeptierten, überarbeitet und akzeptieren nun die CharSequence-Schnittstelle. Wenn Sie also eine Instanz von StringBuilder haben, können Sie, anstatt ein String-Objekt zu extrahieren (was bedeutet, eine neue Objektinstanz zu instanziieren), einfach den StringBuilder selbst übergeben, da er die CharSequence-Schnittstelle implementiert.

Die Schnittstelle Appendable, die von einigen Klassen implementiert wird, hat den gleichen Nutzen für alle Situationen, in denen Zeichen an eine Instanz der zugrundeliegenden konkreten Klassenobjektinstanz angehängt werden können. Alle diese konkreten Klassen implementieren die Schnittstelle Appendable:

BufferedWriter, CharArrayWriter, CharBuffer, FileWriter, FilterWriter, LogStream, OutputStreamWriter, PipedWriter, PrintStream, PrintWriter, StringBuffer, StringBuilder, StringWriter, Writer

0 Stimmen

Es ist schade, dass Schnittstellen wie CharSequence sind so blutarm. Ich wünschte, Java und .NET hätten es zugelassen, dass Schnittstellen eine Standardimplementierung haben, so dass die Leute die Schnittstellen nicht nur zum Zweck der Minimierung von Boilerplate-Code verkleinern würden. Angesichts jeder legitimen CharSequence Implementierung könnte man die meisten Funktionen von String nur mit den oben genannten vier Methoden, aber viele Implementierungen könnten diese Funktionen auf andere Weise viel effizienter ausführen. Leider, auch wenn eine bestimmte Implementierung von CharSequence enthält alles in einem einzigen char[] und könnte viele Aufgaben erfüllen...

0 Stimmen

...Operationen wie indexOf ist es unmöglich, dass ein Anrufer, der mit einer bestimmten Implementierung von CharSequence dazu auffordern könnte, anstatt die charAt um jedes einzelne Zeichen zu untersuchen.

3voto

Daniel Earwicker Punkte 111630

Stellen Sie sich vor, Sie haben ein Produkt namens "Zebra", das durch Plugins erweitert werden kann. Es findet die Plugins, indem es in einem Verzeichnis nach DLLs sucht. Es lädt all diese DLLs und verwendet Reflection, um alle Klassen zu finden, die Folgendes implementieren IZebraPlugin und ruft dann die Methoden dieser Schnittstelle auf, um mit den Plugins zu kommunizieren.

Dadurch ist es völlig unabhängig von einer bestimmten Plugin-Klasse - es ist egal, um welche Klassen es sich handelt. Es ist nur wichtig, dass sie die Schnittstellenspezifikation erfüllen.

Schnittstellen sind ein Weg, um solche Punkte der Erweiterbarkeit zu definieren. Code, der mit einer Schnittstelle kommuniziert, ist eher lose gekoppelt - eigentlich ist er überhaupt nicht an einen anderen spezifischen Code gekoppelt. Er kann mit Plugins zusammenarbeiten, die Jahre später von Leuten geschrieben wurden, die den ursprünglichen Entwickler nie getroffen haben.

Sie könnten stattdessen eine Basisklasse mit virtuellen Funktionen verwenden - alle Plugins würden von der Basisklasse abgeleitet werden. Dies ist jedoch sehr viel einschränkender, da eine Klasse nur eine Basisklasse haben kann, während sie eine beliebige Anzahl von Schnittstellen implementieren kann.

2voto

Q: - ... "Können Sie jede Klasse verwenden, die eine Schnittstelle implementiert?"
A: - Ja.

Q: - ... "Wann sollten Sie das tun?"
A: - Jedes Mal, wenn Sie eine oder mehrere Klassen benötigen, die eine oder mehrere Schnittstellen implementieren.

Wir konnten keine Schnittstelle instanziieren, die nicht von einer Klasse implementiert wurde - Das stimmt.

  • Warum?
  • Da die Schnittstelle nur Methodenprototypen und keine Definitionen enthält (nur Funktionsnamen, nicht ihre Logik)

AnIntf anInst = new Aclass();
// wir könnten dies tun nur wenn Aclass implementiert AnIntf.
// anInst wird eine Aclass-Referenz haben.


Jetzt können wir verstehen, was passiert, wenn Bclass und Cclass das gleiche Dintf implementieren.

Dintf bInst = new Bclass();  
// now we could call all Dintf functions implemented (defined) in Bclass.

Dintf cInst = new Cclass();  
// now we could call all Dintf functions implemented (defined) in Cclass.

Was wir haben: Gleiche Schnittstellenprototypen (Funktionsnamen in der Schnittstelle), aber unterschiedliche Implementierungen aufrufen.

Bibliographie: Prototypen - wikipedia

2voto

Shivam Sugandhi Punkte 57

Eine Schnittstelle ist wie ein Vertrag, bei dem Sie möchten, dass Ihre Implementierungsklasse die im Vertrag (Schnittstelle) beschriebenen Methoden implementiert. Da Java keine Mehrfachvererbung bietet, ist die "Programmierung auf Schnittstelle" ein guter Weg, um Mehrfachvererbung zu erreichen.

Wenn Sie eine Klasse A haben, die bereits eine andere Klasse B erweitert, aber Sie wollen, dass diese Klasse A auch bestimmte Richtlinien befolgt oder einen bestimmten Vertrag implementiert, dann können Sie dies mit der Strategie "Programmierung nach Schnittstelle" erreichen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X