Ich kenne die Syntax, die Regeln für abstrakte Klassen und möchte die Verwendung einer abstrakten Klasse kennen
Abstrakte Klassen können nicht direkt instanziiert, sondern durch andere Klassen erweitert werden
Was ist der Vorteil davon?
Wie unterscheidet es sich von einem Interface?
Ich weiß, dass eine Klasse mehrere Schnittstellen implementieren kann, aber nur eine abstrakte Klasse erweitern kann. Ist das der einzige Unterschied zwischen einer Schnittstelle und einer abstrakten Klasse?
Mir ist die Verwendung eines Interfaces bekannt. Das habe ich aus dem Event Delegation Model von AWT in Java gelernt.
In welchen Situationen sollte ich Klasse als abstrakte Klasse deklarieren? Was ist der Nutzen davon?
java
object-oriented
abstract-class
Vaibhav Jani
quelle
quelle
Antworten:
Mit dieser Antwort lassen sich die Unterschiede zwischen einer abstrakten Klasse und einer Schnittstelle gut erklären , aber sie beantwortet nicht, warum Sie eine deklarieren sollten.
Aus rein technischer Sicht ist es niemals erforderlich , eine Klasse als abstrakt zu deklarieren.
Betrachten Sie die folgenden drei Klassen:
Sie müssen nicht haben , um die Datenbank - Klasse abstrakt zu machen, auch wenn es ein offensichtliches Problem mit seiner Implementierung ist: Wenn Sie dieses Programm schreiben, könnten Sie geben
new Database()
und es wäre gültig, aber es würde nie funktionieren.Unabhängig davon, würden Sie immer noch Polymorphismus bekommen, so lange Ihr Programm nur macht
SqlDatabase
undOracleDatabase
Instanzen, könnten Sie Methoden schreiben wie:Abstrakte Klassen verbessern die Situation, indem sie verhindern, dass ein Entwickler die Basisklasse instanziiert, da ein Entwickler sie als fehlend markiert hat . Es bietet auch Sicherheit beim Kompilieren, sodass Sie sicherstellen können, dass alle Klassen, die Ihre abstrakte Klasse erweitern, die Mindestfunktionalität für die Arbeit bereitstellen, und dass Sie sich nicht darum kümmern müssen, Stub-Methoden (wie die oben genannten) zu platzieren, über die Erben verfügen auf magische Weise zu wissen , dass sie haben eine Methode , um außer Kraft zu setzen , damit es funktioniert zu machen.
Schnittstellen sind ein völlig eigenständiges Thema. Über eine Schnittstelle können Sie beschreiben, welche Vorgänge an einem Objekt ausgeführt werden können. Normalerweise verwenden Sie Schnittstellen, wenn Sie Methoden, Komponenten usw. schreiben, die die Dienste anderer Komponenten oder Objekte verwenden, aber es ist Ihnen egal, von welchem Objekttyp Sie die Dienste erhalten.
Betrachten Sie die folgende Methode:
Sie kümmern sich nicht darum, ob das
database
Objekt von einem bestimmten Objekt erbt, Sie kümmern sich nur darum, dass es eineaddProduct
Methode hat. In diesem Fall ist eine Schnittstelle besser geeignet, als alle Klassen von derselben Basisklasse erben zu lassen.Manchmal funktioniert die Kombination der beiden sehr gut. Zum Beispiel:
Beachten Sie, wie einige Datenbanken von RemoteDatabase erben, um bestimmte Funktionen gemeinsam zu nutzen (z. B. das Herstellen einer Verbindung vor dem Schreiben einer Zeile). FileDatabase ist jedoch eine separate Klasse, die nur implementiert wird
IProductDatabase
.quelle
Ähnlichkeiten
Für die Abstraktion werden abstrakte Klassen und Interfaces benötigt. Sie können nicht mit einem neuen instanziiert werden , sondern können bei der Inversion von Kontrollcontainern oder über Factory-Patterns aufgelöst werden.
Unterschied
Schnittstellen
Abstrakte Klasse
Es ist eigentlich einfach, die Antwort durch einfache Google-Abfrage zu finden .
quelle
In einer abstrakten Klasse können Sie einige Methoden implementieren und den Rest von der Erweiterungsklasse implementieren lassen (erzwingen). Sie können keine Methoden in einer Schnittstelle implementieren. Sie können niemanden zwingen, etwas außer Kraft zu setzen, wenn Sie eine gewöhnliche Klasse erweitern. Mit einer abstrakten Klasse können Sie.
quelle
Abstrakte Klassen sind für "ist ein" Beziehungen und Schnittstellen sind für "können".
Mit abstrakten Klassen können Sie Basisverhalten hinzufügen, damit Programmierer nicht alles codieren müssen, während sie dennoch gezwungen sind, Ihrem Entwurf zu folgen.
quelle
Neben den tiefen technischen Details - wie die Implementierung einiger Methoden für abstrakte Klassen usw. - lautet die Bedeutung wie folgt:
Schnittstellen definieren gemeinsame Fähigkeiten - IEnumerable definiert, dass die Klasse, die diese Schnittstelle implementiert, aufgelistet werden kann. Es sagt nichts über die Klasse selbst aus.
Abstrakte (oder Basis-) Klassen definieren das Verhalten - WebRequest definiert ein gemeinsames Verhalten aller untergeordneten Klassen wie HttpWebRequest usw. Es definiert die Kernbedeutung der Klasse und ihren eigentlichen Zweck - den Zugriff auf Webressourcen.
quelle
Wikipedia-Eintrag .
Der Hauptunterschied zwischen einer Schnittstelle und einer abstrakten Klasse besteht darin, dass eine abstrakte Klasse möglicherweise implementierte Methoden bereitstellt. Mit Interfaces können Sie nur Methoden deklarieren , deren Signatur schreiben. Hier ist ein Beispiel für eine Klasse, die eine abstrakte Klasse erweitert, die zwei Schnittstellen implementiert: (Java)
In diesem Beispiel stellt die MyAbstractClass eine öffentliche Methode bereit, die alle drei Werte ausgibt . In ImpClass müssen Sie getValue1 und getValue2 aus MyInterface1 bzw. MyInterface2 und getValue3 aus der abstrakten Klasse implementieren .
Voilà.
Es gibt weitere Aspekte (Schnittstelle: nur öffentliche Methoden, abstrakte Klasse: geschützte abstrakte und öffentliche abstrakte Methoden), die Sie jedoch selbst lesen können.
Abschließend ist eine abstrakte Klasse, die nur abstrakte Methoden bereitstellt, eine "reine" abstrakte Basisklasse, auch bekannt als Schnittstelle.
quelle
Mit anderen Worten, Sie sollten mit der Frage beginnen: "Teilen sich diese Klassen notwendigerweise die Implementierung oder haben sie nur eine gemeinsame Schnittstelle ?"
Wenn die Antwort gemischt ist, wie z. B. - diese drei Klassen müssen die Implementierung gemeinsam nutzen, aber diese beiden anderen teilen nur ihre API -, können Sie für alle fünf eine Schnittstelle und für diese drei Klassen eine abstrakte Klasse mit der gemeinsamen Schnittstelle erstellen Code.
Es gibt auch andere Möglichkeiten, die Implementierung gemeinsam zu nutzen, z. B. um ein Objekt mit dieser Implementierung zu kapseln (z. B. im Strategiemuster ).
quelle
Sie würden ein Class Abstract deklarieren, wenn Sie nicht möchten, dass der Entwickler (wahrscheinlich Sie selbst) es instanziiert, weil es nicht funktioniert oder keinen Sinn ergibt.
Stellen Sie sich zum Beispiel ein Spiel vor, in dem es verschiedene Arten von Spieleinheiten gibt. Sie alle erben von der Basisklasse
GameEntity
.Diese Klasse wird deklariert,
abstract
da es keinen Sinn macht, sie zu instanziieren. Es deklariert einige Aktionen für die Spielelemente und einige Attribute, aber nirgendwo in dieser Klasse werden diese Attribute initialisiert. Diese Klasse dient als Vorlage für die Spielelemente, ist jedoch nicht dazu gedacht, eigenständig instanziiert und als solche deklariert zu werdenabstract
.In Bezug auf den Unterschied in der Verwendung zwischen einer abstrakten Klasse und einer Schnittstelle:
Aus meiner Sicht ist eine Schnittstelle eine Möglichkeit, polymorphes Verhalten zu erreichen, ohne durch den Mechanismus der einmaligen Vererbung einiger Sprachen eingeschränkt zu sein.
Kehren wir als Beispiel zum Spiel zurück. Betrachten Sie eine Klasse,
Enemy
die von abgeleitet istGameEntity
. Diese Klasse hat eine MethodeattackMeFromDistance(RangedAttacker attacker)
. Diese Methode soll es Einheiten ermöglichen, den Feind von weitem anzugreifen.Wie Sie sehen, nimmt diese Methode einen
RangedAttacker
Typ als Parameter an. Alle Spieleinheiten erben jedoch bereits vonGameEntity
. Sie können keine weitere Klasse erweitern.Nehmen Sie den Unterricht
Mage
undArcher
zum Beispiel. Wir möchten, dass beide als Parameter in derattackMeFromDistance(RangedAttacker attacker)
Methode akzeptiert werden, aber sie sind bereits von abgeleitetGameEntity
.Um dies zu lösen, erstellen wir eine neue Schnittstelle:
Eine Klasse, die diese Schnittstelle implementiert, muss die
attackFromDistance()
Methode implementieren. Auf diese Weise wird sichergestellt, dass sie über verschiedene Angriffsmöglichkeiten verfügt. Dies bedeutet, dass dieattackMeFromDistance
Methode jetzt sicher Klassen akzeptieren kann, die diese Schnittstelle implementieren. Das ErstellenMage
undArcher
Implementieren dieser Schnittstelle löst unser Problem.Für mich ist das die Kraft der Schnittstellen.
Zusammenfassend würde man normalerweise eine abstrakte Klasse verwenden, wenn man für einige Klassen eine Basisklasse haben möchte, aber es wäre nicht sinnvoll, sie selbst zu instanziieren (oder in einem Fall, in dem es
abstract
Methoden gibt, die es sein müssen) implementiert von den Unterklassen, und in diesem Fall würde der Compiler Sie zwingen, die Klasse zu machenabstract
). Sie würden eine Schnittstelle verwenden, um polymorphes Verhalten zu erzielen, ohne durch den Mechanismus der einmaligen Vererbung eingeschränkt zu sein.quelle
quelle