927 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?!?

87 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.

10voto

Kevin Le - Khnle Punkte 9990

Wenn Sie in Java programmieren, ist JDBC ein gutes Beispiel. JDBC definiert eine Reihe von Schnittstellen, sagt aber nichts über die Implementierung aus. Ihre Anwendungen können für diesen Satz von Schnittstellen geschrieben werden. Theoretisch können Sie irgendeinen JDBC-Treiber auswählen und Ihre Anwendung würde einfach funktionieren. Wenn Sie feststellen, dass es einen schnelleren oder "besseren" oder billigeren JDBC-Treiber gibt, oder aus welchem Grund auch immer, können Sie wiederum theoretisch Ihre Eigenschaftsdatei neu konfigurieren, und Ihre Anwendung würde weiterhin funktionieren, ohne dass Sie etwas an Ihrer Anwendung ändern müssten.

0 Stimmen

Das ist nicht nur nützlich, wenn ein besserer Treiber verfügbar wird, sondern ermöglicht auch einen kompletten Wechsel des Datenbankanbieters.

3 Stimmen

JDBC ist so schlecht, dass es ersetzt werden muss. Finden Sie ein anderes Beispiel.

0 Stimmen

JDBC ist schlecht, aber nicht aus einem Grund, der mit Schnittstelle vs. Implementierung oder Abstraktionsebenen zu tun hat. Zur Veranschaulichung des fraglichen Konzepts ist es also geradezu perfekt.

8voto

dbones Punkte 4296

Die Programmierung nach Schnittstellen ist großartig, sie fördert die lose Kopplung. Wie @lassevk erwähnte, ist die Inversion der Kontrolle eine großartige Anwendung davon.

Außerdem sollten Sie sich mit den SOLID-Prinzipien befassen . hier ist eine Video-Serie

Es wird ein hart kodiertes (stark gekoppeltes Beispiel) durchlaufen, dann werden Schnittstellen betrachtet, und schließlich wird ein IoC/DI-Tool (NInject) vorgestellt.

8voto

nonopolarity Punkte 138211

Ich bin ein Nachzügler in dieser Frage, aber ich möchte hier erwähnen, dass die Zeile "Program to an interface, not an implementation" in dem GoF (Gang of Four) Design Patterns Buch gut diskutiert wurde.

Darin heißt es auf S. 18:

Programm für eine Schnittstelle, nicht für eine Implementierung

Deklarieren Sie Variablen nicht als Instanzen von bestimmten konkreten Klassen. Beziehen Sie sich stattdessen nur auf eine Schnittstelle, die durch eine abstrakte Klasse definiert ist. Sie werden feststellen, dass dies ein gemeinsames Thema der Entwurfsmuster in diesem Buch ist.

und darüber hinaus begann es mit:

Es gibt zwei Vorteile, wenn Objekte ausschließlich über die von abstrakten Klassen definierte Schnittstelle bearbeitet werden:

  1. Die Kunden wissen nicht, welche Arten von Objekten sie verwenden, solange die Objekte die von den Kunden erwartete Schnittstelle einhalten.
  2. Die Kunden kennen die Klassen, die diese Objekte implementieren, nicht. Die Clients kennen nur die abstrakte(n) Klasse(n), die die Schnittstelle definieren.

Mit anderen Worten: Schreiben Sie Ihren Unterricht nicht so, dass er eine quack() Methode für Enten, und dann eine bark() Methode für Hunde, weil sie zu spezifisch für eine bestimmte Implementierung einer Klasse (oder Unterklasse) sind. Schreiben Sie die Methode stattdessen mit Namen, die allgemein genug sind, um in der Basisklasse verwendet zu werden, wie z. B. giveSound() ou move() so dass sie für Enten, Hunde oder sogar Autos verwendet werden können, und dann kann der Kunde Ihrer Klassen einfach sagen .giveSound() anstatt darüber nachzudenken, ob man quack() ou bark() oder sogar den Typ bestimmen, bevor die richtige Nachricht an das Objekt gesendet wird.

6voto

e11s Punkte 4075

Als Ergänzung zu den bereits vorhandenen Beiträgen ist es bei großen Projekten manchmal hilfreich, an Schnittstellen zu kodieren, wenn die Entwickler gleichzeitig an verschiedenen Komponenten arbeiten. Alles, was Sie brauchen, ist, Schnittstellen im Voraus zu definieren und Code für sie zu schreiben, während andere Entwickler Code für die Schnittstelle schreiben, die Sie implementieren.

5voto

jaco0646 Punkte 13032

Bei den bisherigen Antworten lag der Schwerpunkt auf der Programmierung auf einer Abstraktion, um die Erweiterbarkeit und die lose Kopplung zu gewährleisten. Dies sind zwar sehr wichtige Punkte, Lesbarkeit ist ebenso wichtig. Die Lesbarkeit ermöglicht es anderen (und Ihrem zukünftigen Ich), den Code mit minimalem Aufwand zu verstehen. Aus diesem Grund nutzt die Lesbarkeit Abstraktionen.

Eine Abstraktion ist per Definition einfacher als ihre Implementierung. Eine Abstraktion lässt Details weg, um das Wesentliche oder den Zweck einer Sache zu vermitteln, aber nicht mehr. Da Abstraktionen einfacher sind, kann ich im Vergleich zu Implementierungen viel mehr von ihnen auf einmal in meinem Kopf unterbringen.

Als Programmierer (in jeder Sprache) habe ich eine allgemeine Vorstellung von einer List die ganze Zeit in meinem Kopf. Vor allem eine List erlaubt den zufälligen Zugriff, die Duplizierung von Elementen und die Aufrechterhaltung der Ordnung. Wenn ich eine Erklärung wie diese sehe: List myList = new ArrayList() Glaube ich, cool ist dies ein List das in der (grundlegenden) Weise verwendet wird, die ich verstehe; und ich muss nicht weiter darüber nachdenken.

Andererseits trage ich nicht die spezifischen Implementierungsdetails von ArrayList in meinem Kopf. Wenn ich also sehe, ArrayList myList = new ArrayList() . denke ich, Oh-oh diese ArrayList muss in einer Weise verwendet werden, die nicht unter die List Schnittstelle. Jetzt muss ich alle Verwendungszwecke dieser Schnittstelle aufspüren ArrayList um zu verstehen, warum, denn sonst kann ich diesen Code nicht vollständig verstehen. Noch verwirrender wird es, wenn ich feststelle, dass 100 % der Verwendungen dieses ArrayList faire entsprechen dem List Schnittstelle. Dann frage ich mich... gab es einen Code, der sich auf ArrayList Implementierungsdetails, die gelöscht wurden? War der Programmierer, der sie instanziiert hat, einfach nur inkompetent? Ist diese Anwendung zur Laufzeit auf irgendeine Weise an diese spezielle Implementierung gebunden? Auf eine Weise, die ich nicht verstehe?

Ich bin jetzt verwirrt und unsicher über diese Anwendung, und alles, worüber wir reden, ist eine einfache List . Was wäre, wenn es sich um ein komplexes Geschäftsobjekt handeln würde, das seine Schnittstelle ignoriert? Dann reicht mein Wissen über die Geschäftsdomäne nicht aus, um den Zweck des Codes zu verstehen.

Selbst wenn ich also eine List streng innerhalb einer private Methode (nichts, was andere Anwendungen kaputt machen würde, wenn es geändert würde, und ich könnte jede Verwendung in meiner IDE leicht finden/ersetzen), ist es immer noch von Vorteil für die Lesbarkeit, auf eine Abstraktion zu programmieren. Denn Abstraktionen sind einfacher als Implementierungsdetails. Man könnte sagen, dass die Programmierung nach Abstraktionen eine Möglichkeit ist, sich an die KISS Prinzip.

1 Stimmen

Sehr gute Erklärung. Dieses Argument ist wirklich wertvoll.

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