Wenn ich eine Schnittstelle implementiere, wird sie als Vererbung bezeichnet?

31

Wenn meine Klasse implementseine Schnittstelle ist, kann ich dann sagen, dass ich der Vererbung folge? Ich weiß, wenn eine Klasse eine extendsandere Klasse ist, dann ist es Vererbung.

RajeeV VenkaT
quelle
7
Jodrells Kommentar ist einfach falsch. Das Implementieren einer Schnittstelle ist in der Tat eine Vererbung, und das Erben einer Schnittstelle von einer anderen ist eine Vererbung. Woher wissen wir? Indem wir das Wort definieren, das wir verwenden. Vererbung ist die Eigenschaft, dass die vererbbaren Elemente eines Typs auch Elemente eines anderen Typs sind. Nach dieser Definition hat eine Klasse, die eine Schnittstelle implementiert, alle Methoden der Schnittstelle geerbt. Betrachten Sie einfach die Klasse und die Schnittstelle und Sie werden feststellen, dass sie in einem korrekten Programm dieselben Mitglieder haben.
Eric Lippert
Ich habe es deaktiviert und bin mit mehr Verwirrung gegangen.
RajeeV VenkaT
18
Ich denke, Sie verbringen viel Zeit mit einer Wortdefinition, die Ihnen nicht viel Nutzen bringt. Letztendlich wissen wir alle, was die Implementierung einer Schnittstelle bedeutet und ob sie als "Vererbung" betrachtet wird, spielt für Ihre tägliche Arbeit keine Rolle.
Robert Harvey
3
Ich stimme (meistens) Robert zu. Ich denke, es ist wirklich wertvoll, die genauen technischen Bedeutungen von Jargon-Wörtern zu verstehen, wie sie in verschiedenen Zusammenhängen verwendet werden. Aber Robert hat Recht, dass es von weit größerem Nutzen ist, die praktischen Auswirkungen zu verstehen! Wie können Sie Vererbung verwenden, um Ihren Code sicherer zu machen? Testbarer? Mehrweg? Flexibler? Und so weiter. Zu wissen, dass Mitglieder von Basistypen auch Mitglieder von abgeleiteten Typen sind, ist großartig, aber es ist noch besser zu wissen, wie man es effektiv einsetzt.
Eric Lippert

Antworten:

78

UPDATE: Ich habe diese Antwort überarbeitet. In den Kommentaren, die es verdient haben, hervorgehoben zu werden, wurden einige gute Punkte angesprochen.

Wenn meine Klasse eine Schnittstelle implementiert, kann ich dann sagen, dass ich der Vererbung folge?

Es ist nicht ganz klar, was Sie mit "Nachvererbung" meinen. Lassen Sie uns eine etwas andere Frage stellen?

Was ist Vererbung?

  • Wenn Mitglieder eines Typs X als Mitglieder eines anderen Typs Y betrachtet werden, werden diese Mitglieder von Y von X geerbt .
  • Zwischen einigen Typen besteht eine Vererbungsbeziehung. das heißt, für einige Typen X und Y sagen wir "Y erbt von X".

Diese unterscheiden sich geringfügig. Das ist bedauerlich, weil es verwirrend ist.

Welche Verwirrungen ergeben sich typischerweise aus dieser subtilen Unterscheidung?

Es kann zu Verwirrung kommen, weil die Leute die Vererbung als einen Mechanismus zur Weitergabe von Implementierungsdetails ansehen. Obwohl es sich um einen solchen Mechanismus handelt, funktioniert dieser Mechanismus, indem Mitglieder geteilt werden . Diese Mitglieder müssen keine Implementierungen haben! Wie wir sehen werden, können sie abstrakt sein.

Ich persönlich wäre glücklicher, wenn die Java- und C # -Spezifikationen ein anderes Wort als "inherits" verwenden würden, um die Beziehung zwischen Schnittstellenmethoden und Klassen zu beschreiben, um diese Verwirrung zu vermeiden. Aber sie tun es nicht, und wir müssen uns aus den Spezifikationen herleiten, nicht gegen sie.

Werden in Java Schnittstellenmember von Klassen geerbt, die sie implementieren?

Ja, manche sind. Weitere Informationen finden Sie in Abschnitt 8.4.8 der Java-Spezifikation, den ich hier für Sie zitiere.

Eine Klasse C erbt von ihrer direkten Superklasse und direkten Superschnittstelle alle abstrakten und Standardmethoden m, für die alle der folgenden Bedingungen zutreffen: [...]

Wenn Sie sagen, dass eine Klasse eine Schnittstelle implementiert, erbt die Klasse die abstrakten und Standardmethoden dieser Schnittstelle . (Natürlich habe ich die folgenden Bedingungen ausgelassen; Einzelheiten finden Sie in der Spezifikation. Insbesondere wird nicht davon ausgegangen, dass eine Klasse, die ein Mitglied einer Schnittstelle implementiert, dieses Mitglied geerbt hat. Ist dies wiederum verwirrend? Ja.)

Sagen wir in Java normalerweise, dass eine Klasse von einer Schnittstelle erbt?

Normalerweise würden wir sagen, dass eine Klasse eine Schnittstelle implementiert . Wie oben erwähnt, kann eine Klasse Mitglieder von einer Schnittstelle erben und dennoch nicht von der Schnittstelle erben. Was verwirrend ist, ja.

Ist diese subtile Unterscheidung für die tägliche Arbeit von Bedeutung?

Normalerweise nicht. Diese Art der engen Analyse der Spezifikation ist für Compiler-Autoren nützlicher als für Branchenentwickler. Es ist wichtiger zu verstehen, wann eine Schnittstelle verwendet werden soll, als eine genaue Definition von "Erben von" zu erhalten.

Eric Lippert
quelle
4
Ich kann nicht mit einem kanonischen Verweis argumentieren. Wenn sich Spezifikationen unterscheiden, werden einfache Begriffe semantisch überladen und nicht eindeutig im Kontext. Die Frage ist getaggt mit, javaso dass dies die richtige Antwort ist, es sei denn, das OP bedeutete etwas anderes java:-)
Jodrell
5
Obwohl die Frage mit Java markiert ist, finde ich es problematisch, eine Sprachspezifikation für einen Oberbegriff zu zitieren. Viele Sprachen haben Benutzeroberflächen, und ihre Sprachspezifikationen verwenden möglicherweise einen anderen Begriff. Daher kann die Verwendung eines Java-spezifischen Begriffs im Gespräch mit Entwicklern, die X-Lang verwenden, verwirrend sein.
Thomas Owens
5
@ThomasOwens: Ich stimme zu, dass dieses Szenario häufig vorkommt und stimme Ihrer Schlussfolgerung überhaupt nicht zu. Die Lösung des von Ihnen beschriebenen Kommunikationsproblems besteht darin , alle Beteiligten über die genaue Bedeutung der Wörter im jeweiligen Kontext zu unterrichten . Spezifikationen sind vorhanden, um diese Klarheit zu gewährleisten. benutze sie!
Eric Lippert
5
Warum sollte die Java-Sprachspezifikation hier das letzte Wort haben? Sprachspezifikationen behaupten oft Dinge, mit denen der "allgemeine Entwickler" in Bezug auf die Terminologie nicht einverstanden ist.
Benjamin Gruenbaum
5
@BenjaminGruenbaum: Weiß ich nicht. Diese Entwickler sind falsch und nehmen es oft auf sich, andere über ihre falschen Überzeugungen zu "erziehen". Sie würden nicht glauben, wie viele Bücher in Programmiersprachen ich reparieren musste, weil die Autoren einige völlig verrückte Vorstellungen über VB, C #, JavaScript usw. hatten, die in keiner Weise korrekt waren. (Jon Skeet war nicht dabei; C # In Depth war von Anfang an korrekt! Ich habe noch nie so wenige Kommentare zu einem Buch abgegeben und wurde trotzdem bezahlt.)
Eric Lippert
26

Vererbung bedeutet das Schreiben einer neuen Unterklasse für eine Superklasse. Das Schreiben einer neuen Klasse für eine Schnittstelle implementiert diese Schnittstelle. (Und das Schreiben einer neuen Schnittstelle auf der Grundlage einer alten Schnittstelle erweitert diese Schnittstelle.)

Der einzig richtige Begriff, der für alle drei Möglichkeiten gilt, ist Subtypisierung . Nicht jeder Subtyp ist eine Subklasse.

Kilian Foth
quelle
1
GoF Buch scheinen Schnittstelle Vererbung geeigneten Begriff zu berücksichtigen zu beschreiben Subtypisierung (Abschnitt 1.6 Klasse gegen Schnittstelle Vererbung)
gnat
"Ich habe einmal an einem Java-Anwendertreffen teilgenommen, bei dem James Gosling (Javas Erfinder) als Sprecher auftrat. Während der denkwürdigen Fragerunde fragte ihn jemand:" Wenn Sie noch einmal Java machen könnten, was würden Sie ändern? " Lassen Sie Klassen aus ", antwortete er. Er erklärte, dass das eigentliche Problem nicht Klassen an sich seien, sondern die Implementierungsvererbung (die Extended-Beziehung). Die Schnittstellenvererbung (die Implements-Beziehung) ist vorzuziehen. Sie sollten die Implementierungsvererbung nach Möglichkeit vermeiden." javaworld.com/article/2073649/core-java/…
Ricardoramos
1

Mit Unterklassen , Sie

  • erben Sie den Status der Oberklasse (alle Instanzvariablen, ob Sie sie sehen oder nicht)
  • tatsächliche Implementierungen erben (alle nicht abstrakten Methoden)

Mit Schnittstellen erfüllen Sie einen Vertrag, indem Sie die deklarierten Methoden implementieren .

Das ist die klassische Sichtweise. Jetzt mit Java 8 werden die Schnittstellen eine Mischung:

  • Sie erben immer noch keinen Status (da Schnittstellen immer noch keine Instanzvariablen haben)
  • Sie können jetzt Standardimplementierungen von der Schnittstelle übernehmen

Würde die Implementierung einer Schnittstelle, deren Methoden alle Standardimplementierungen aufweisen, immer noch als "implementieren" oder eher als Erweiterung gelten? Ich konnte es nicht sagen. Da dieser Fall ziemlich weit hergeholt ist (diese tatsächlich aktivierte zustandslose Mehrfachvererbung), würde ich "Vererbung" immer noch nur bei Unterklassen verwenden.

Peter Walser
quelle