840 Stimmen

Schnittstelle vs. Basisklasse

Wann sollte ich eine Schnittstelle und wann eine Basisklasse verwenden?

Sollte es immer eine Schnittstelle sein, wenn ich keine Basisimplementierung der Methoden definieren möchte?

Wenn ich eine Hunde- und Katzenklasse habe. Warum sollte ich IPet anstelle von PetBase implementieren wollen? Ich kann verstehen, mit Schnittstellen für ISheds oder IBarks (IMakesNoise?), weil diese auf ein Haustier von Haustier Basis platziert werden können, aber ich verstehe nicht, welche für eine allgemeine Pet verwenden.

11 Stimmen

Nur ein Punkt, den Sie meiner Meinung nach berücksichtigen sollten - Schnittstellen können verschiedene Einschränkungen mit sich bringen, derer Sie sich möglicherweise erst in sehr späten Phasen bewusst sind. Zum Beispiel mit .NET können Sie nicht serialisieren eine Schnittstelle Mitglied Variable, so dass, wenn Sie eine Klasse Zoo und ein Mitglied Variable Array von IAnimals haben Sie nicht in der Lage, Zoo serialisieren (und das bedeutet, schreiben WebServices oder andere Dinge, die eine Serialisierung wäre ein Schmerz).

2 Stimmen

Diese Frage könnte helfen, das Konzept der Schnittstellen zu verstehen. stackoverflow.com/q/8531292/1055241

0 Stimmen

Ich bin nur neugierig. Ich traf in der CLR über C# den folgenden Auszug: I tend to prefer using the interface technique over the base type technique because the base type technique doesn’t allow the developer to choose the base type that works best in a particular situation. . Ich kann nicht begreifen, was in dem Auszug gemeint ist. Wir können einige Basistypen erstellen und für jeden von ihnen einen abgeleiteten Typ erstellen, so dass ein Entwickler einen Basistyp auswählen kann. Könnte mir bitte jemand erklären, was ich übersehe? Ich glaube, es kann ein Teil dieser Frage sein. Oder sollte ich eine andere Frage zu dem spezifischen Auszug stellen?

547voto

Jon Limjap Punkte 92084

Nehmen wir Ihr Beispiel einer Hunde- und einer Katzenklasse und veranschaulichen wir es mit C#:

Sowohl ein Hund als auch eine Katze sind Tiere, genauer gesagt, vierbeinige Säugetiere (Tiere sind viel zu allgemein). Nehmen wir an, dass Sie eine abstrakte Klasse Mammal für beide haben:

public abstract class Mammal

Diese Basisklasse wird wahrscheinlich Standardmethoden haben, wie z.B.:

  • Futtermittel
  • Mate

Es handelt sich dabei um Verhaltensweisen, die bei beiden Arten mehr oder weniger gleich umgesetzt werden. Um dies zu definieren, müssen Sie:

public class Dog : Mammal
public class Cat : Mammal

Nehmen wir nun an, dass es andere Säugetiere gibt, die wir normalerweise in einem Zoo sehen:

public class Giraffe : Mammal
public class Rhinoceros : Mammal
public class Hippopotamus : Mammal

Dies gilt auch weiterhin, da der Kern der Funktionalität Feed() y Mate() wird immer noch derselbe sein.

Giraffen, Nashörner und Nilpferde sind jedoch nicht gerade Tiere, die man als Haustiere halten kann. Hier wird eine Schnittstelle nützlich sein:

public interface IPettable
{
    IList<Trick> Tricks{get; set;}
    void Bathe();
    void Train(Trick t);
}

Die Implementierung des oben genannten Vertrages wird bei einer Katze und einem Hund nicht gleich sein; ihre Implementierungen in eine abstrakte Klasse zu vererben, wäre eine schlechte Idee.

Ihre Definitionen für Hund und Katze sollten nun wie folgt aussehen:

public class Dog : Mammal, IPettable
public class Cat : Mammal, IPettable

Theoretisch kann man sie von einer höheren Basisklasse aus überschreiben, aber im Wesentlichen erlaubt eine Schnittstelle, nur die Dinge hinzuzufügen, die man in einer Klasse braucht, ohne die Notwendigkeit der Vererbung.

Da man in der Regel nur von einer abstrakten Klasse erben kann (in den meisten statisch typisierten OO-Sprachen, d.h. mit Ausnahme von C++), aber in der Lage ist, mehrere Schnittstellen zu implementieren, ist es möglich, Objekte in einem strikten Rahmen zu konstruieren. nach Bedarf Basis.

168 Stimmen

Ich glaube nicht, dass es so einfach ist. Sie haben die Frage (Anforderungen) leicht verändert, damit die Schnittstelle mehr Sinn ergibt. Sie sollten sich immer fragen, ob Sie einen Vertrag (Schnittstelle) oder eine gemeinsame Implementierung (Basisklasse) definieren.

20 Stimmen

Die Schnittstelle ist ein Vertrag. Sie legen nur den Teil des Vertrags offen, den ein Dienst benötigt. Wenn Sie einen "PettingZoo" haben, wollen Sie dem Benutzer sicher nicht das "Mate"-ing offenlegen!

10 Stimmen

@David Touche, obwohl ich es getan habe, um besser zu verdeutlichen, wozu eine Schnittstelle und wozu eine abstrakte Klasse dient, im Gegensatz zu seinem Verständnis. Ein Hund und eine Katze scheinen keine starre Anforderung zu sein!

155voto

Marcio Aguiar Punkte 13577

Nun, Josh Bloch sagte selbst in Effektives Java 2d :

Schnittstellen gegenüber abstrakten Klassen bevorzugen

Einige wichtige Punkte:

  • Vorhandene Klassen können leicht nachgerüstet werden, um eine neue Schnittstelle . Alles, was Sie tun müssen, ist hinzufügen die erforderlichen Methoden hinzuzufügen, falls sie noch nicht und der Klasse eine implements-Klausel hinzufügen der Klassendeklaration hinzufügen.

  • Schnittstellen sind ideal für die Definition von Mixins . Grob gesagt, ist ein Mixin ist ein Typ, den eine Klasse zusätzlich zu ihrem "primären Typ" implementieren kann Typ" implementieren kann, um zu deklarieren, dass sie ein ein optionales Verhalten bietet. Zum Beispiel, Comparable ist eine Mixin-Schnittstelle, die einer Klasse erlaubt, zu deklarieren, dass ihre Instanzen geordnet sind in Bezug auf anderen gegenseitig vergleichbaren Objekten geordnet sind.

  • Schnittstellen ermöglichen die Konstruktion von nichthierarchischen Typen Frameworks . Typenhierarchien sind großartig, um einige Dinge zu organisieren, aber andere Dinge lassen sich nicht sauber in eine starre Hierarchie.

  • Schnittstellen ermöglichen sichere, leistungsstarke Funktionserweiterungen über die wrap- per class idiom. Wenn Sie abstrakte Klassen zur Definition von Typen verwenden, überlassen Sie dem Programmierer, der Typen hinzufügen möchte, die Möglichkeit Funktionalität hinzufügen will, keine andere Wahl als Vererbung zu verwenden.

Außerdem können Sie die Vorzüge von Schnittstellen und abstrakten Klassen kombinieren, indem Sie ein abstraktes Grundgerüst Implementierungsklasse anbieten, die zu jeder nicht-trivialen Schnittstelle, die Sie exportieren, eine abstrakte Implementierungsklasse bereitstellen.

Andererseits lassen sich Schnittstellen nur sehr schwer weiterentwickeln. Wenn man eine Methode zu einer Schnittstelle hinzufügt, werden alle ihre Implementierungen zerstört.

PS: Kaufen Sie das Buch. Es ist noch viel ausführlicher.

76 Stimmen

Wenn eine Schnittstelle geändert werden muss, besteht die beste Möglichkeit darin, eine neue Schnittstelle zu erstellen, die von der alten Schnittstelle erbt, ohne diese zu zerstören. Dadurch bleiben die vorhandenen Implementierungen erhalten und Sie können in der neuen Schnittstelle tun, was Sie wollen.

5 Stimmen

Haben wir das "Prinzip der Schnittstellentrennung". Dieses Prinzip lehrt uns, beim Schreiben unserer Schnittstellen darauf zu achten, dass wir nur Methoden hinzufügen, die dort sein sollten. Wenn wir Methoden hinzufügen, die dort nicht sein sollten, müssen die Klassen, die die Schnittstelle implementieren, diese Methoden ebenfalls implementieren. Wenn wir zum Beispiel eine Schnittstelle namens Worker erstellen und eine Methode Mittagspause hinzufügen, müssen alle Worker diese implementieren. Was ist, wenn der Arbeiter ein Roboter ist? Schnittstellen, die Methoden enthalten, die nicht spezifisch für sie sind, werden als verschmutzte oder fette Schnittstellen bezeichnet.

3 Stimmen

Seit Java 8 ermöglichen Default-Methoden das Hinzufügen neuer Funktionen zu den Schnittstellen und gewährleisten die Abwärtskompatibilität für bestehende Klassen, die diese Schnittstelle implementieren. Standardmethoden werden standardmäßig aufgerufen, wenn sie in der implementierenden Klasse nicht überschrieben werden. Alle implementierenden Klassen können entweder die Standardmethoden überschreiben oder sie direkt mit instance.defaultMethod() aufrufen.

149voto

Thomas Danecker Punkte 4500

Schnittstellen und Basisklassen stellen zwei verschiedene Formen von Beziehungen dar.

Vererbung (Basisklassen) stellen eine "ist-a"-Beziehung dar. Ein Hund oder eine Katze ist z. B. ein" Haustier. Diese Beziehung stellt immer die (einzige) Zweck der Klasse (in Verbindung mit dem "Grundsatz der einzigen Verantwortung" ).

Schnittstellen repräsentieren andererseits zusätzliche Eigenschaften einer Klasse. Ich würde es eine "ist"-Beziehung nennen, wie in " Foo ist wegwerfbar", daher die IDisposable Schnittstelle in C#.

15 Stimmen

Von allen Antworten ist diese am besten geeignet, um sich kurz zu fassen, ohne an Klarheit zu verlieren

1 Stimmen

Jemand hat mir einmal gesagt, ich solle eine Schnittstelle verwenden, wenn es eine "has-a"-Beziehung gibt. Ich bin mir nicht sicher, ob das immer zutrifft; Mein Laptop hat einen Bildschirm, also sollte er IScreen implementieren oder eine Eigenschaft Screen haben? Letzteres scheint mir natürlicher zu sein.

2 Stimmen

@berend lustig, dass du das schreibst, denn die Bildschirme sind über Schnittstellen implementiert - VGA, HDMI usw.

114voto

Jason Cohen Punkte 78227

Der moderne Stil soll IPet definieren et PetBase.

Der Vorteil der Schnittstelle ist, dass anderer Code sie ohne jegliche Bindung an anderen ausführbaren Code nutzen kann. Völlig "sauber". Auch Schnittstellen können gemischt werden.

Basisklassen sind jedoch für einfache Implementierungen und allgemeine Hilfsprogramme nützlich. Bieten Sie also auch eine abstrakte Basisklasse an, um Zeit und Code zu sparen.

0 Stimmen

Du kannst deinen Kuchen essen und ihn auch essen!

0 Stimmen

Jawohl! Und mit modernen IDEs wird sogar der Boiler-Plate-Code für Sie geschrieben (und einige Sprachen brauchen nicht einmal DAS)

4 Stimmen

Eine Schnittstelle definiert, wie andere Klassen Ihren Code verwenden können. Eine Basisklasse hilft Implementierern, Ihre Schnittstelle zu implementieren. Zwei verschiedene Dinge für zwei verschiedene Zwecke.

68voto

Gishu Punkte 130442

Schnittstellen

  • Die meisten Sprachen erlauben es, mehrere Schnittstellen zu implementieren
  • Die Änderung einer Schnittstelle ist eine grundlegende Änderung. Alle Implementierungen müssen neu kompiliert/geändert werden.
  • Alle Mitglieder sind öffentlich. Die Implementierungen müssen alle Mitglieder implementieren.
  • Schnittstellen helfen bei der Entkopplung. Sie können Mock-Frameworks verwenden, um alles, was sich hinter einer Schnittstelle befindet, zu verbergen
  • Schnittstellen weisen normalerweise auf eine Art von Verhalten hin
  • Schnittstellenimplementierungen sind voneinander entkoppelt / isoliert

Basis-Klassen

  • Ermöglicht Ihnen das Hinzufügen einiger Standard Implementierung, die Sie durch Ableitung kostenlos erhalten (ab C# 8.0 können Sie über eine Schnittstelle eine Standardimplementierung erhalten)
  • Außer in C++ können Sie nur von einer Klasse ableiten. Selbst wenn man von mehreren Klassen ableiten kann, ist das in der Regel eine schlechte Idee.
  • Die Änderung der Basisklasse ist relativ einfach. Ableitungen müssen nichts Besonderes tun
  • Basisklassen können geschützte und öffentliche Funktionen deklarieren, auf die von Ableitungen zugegriffen werden kann
  • Abstrakte Basisklassen können nicht einfach wie Schnittstellen gespottet werden
  • Basisklassen weisen normalerweise auf eine Typenhierarchie hin (IS A)
  • Abgeleitete Klassen können von einem bestimmten Basisverhalten abhängen (sie haben eine genaue Kenntnis der übergeordneten Implementierung). Die Dinge können chaotisch werden, wenn Sie eine Änderung an der Basisimplementierung für einen Typ vornehmen und die anderen kaputt machen.

0 Stimmen

Hinweis: In den Entwurfsrichtlinien des Frameworks wird die Verwendung von Basisklassen (im Gegensatz zu Schnittstellen) empfohlen, da diese besser versioniert sind. Das Hinzufügen einer neuen Methode zu einer abstrakten Basisklasse in vNext ist eine nicht-brechende Änderung

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