Was ist der Unterschied zwischen abstrakter Klasse und Schnittstelle in Python?
quelle
Was ist der Unterschied zwischen abstrakter Klasse und Schnittstelle in Python?
Was Sie manchmal sehen werden, ist Folgendes:
class Abstract1( object ):
"""Some description that tells you it's abstract,
often listing the methods you're expected to supply."""
def aMethod( self ):
raise NotImplementedError( "Should have implemented this" )
Da Python keinen formalen Schnittstellenvertrag hat (und nicht benötigt), gibt es keine Unterscheidung zwischen Abstraktion und Schnittstelle im Java-Stil. Wenn jemand versucht, eine formale Schnittstelle zu definieren, handelt es sich auch um eine abstrakte Klasse. Die einzigen Unterschiede wären in der angegebenen Absicht in der Dokumentzeichenfolge.
Und der Unterschied zwischen abstrakt und Schnittstelle ist eine haarsträubende Sache, wenn Sie Enten tippen.
Java verwendet Schnittstellen, da es keine Mehrfachvererbung hat.
Da Python mehrfach vererbt ist, wird möglicherweise auch so etwas angezeigt
class SomeAbstraction( object ):
pass # lots of stuff - but missing something
class Mixin1( object ):
def something( self ):
pass # one implementation
class Mixin2( object ):
def something( self ):
pass # another
class Concrete1( SomeAbstraction, Mixin1 ):
pass
class Concrete2( SomeAbstraction, Mixin2 ):
pass
Dies verwendet eine Art abstrakte Superklasse mit Mixins, um konkrete Unterklassen zu erstellen, die nicht zusammenhängend sind.
NotImplementedError("Class %s doesn't implement aMethod()" % (self.__class__.__name__))
ist informativer Fehlermeldung :)Eine Schnittstelle für ein Objekt besteht aus einer Reihe von Methoden und Attributen für dieses Objekt.
In Python können wir eine abstrakte Basisklasse verwenden, um eine Schnittstelle zu definieren und zu erzwingen.
Verwenden einer abstrakten Basisklasse
Angenommen, wir möchten eine der abstrakten Basisklassen aus dem
collections
Modul verwenden:Wenn wir versuchen, es zu verwenden, erhalten wir eine,
TypeError
weil die von uns erstellte Klasse das erwartete Verhalten von Mengen nicht unterstützt:Also wir sind bei implementieren dest
__contains__
,__iter__
und__len__
. Verwenden wir dieses Implementierungsbeispiel aus der Dokumentation :Implementierung: Erstellen einer abstrakten Basisklasse
Wir können unsere eigene abstrakte Basisklasse erstellen, indem wir die Metaklasse auf relevante Methoden setzen
abc.ABCMeta
und denabc.abstractmethod
Dekorator verwenden. Die Metaklasse fügt dem__abstractmethods__
Attribut die dekorierten Funktionen hinzu und verhindert so die Instanziierung, bis diese definiert sind.Zum Beispiel wird "effizient" als etwas definiert, das in Worten ausgedrückt werden kann. Angenommen, wir wollten in Python 2 eine abstrakte Basisklasse definieren, die effektiv ist:
Oder in Python 3 mit der geringfügigen Änderung der Metaklassendeklaration:
Wenn wir nun versuchen, ein effektives Objekt zu erstellen, ohne die Schnittstelle zu implementieren:
und versuchen Sie es zu instanziieren:
Uns wird gesagt, dass wir den Job noch nicht beendet haben.
Wenn wir nun die erwartete Schnittstelle bereitstellen:
Wir können dann die konkrete Version der Klasse verwenden, die von der abstrakten abgeleitet ist:
Es gibt andere Dinge, die wir damit tun könnten, wie das Registrieren virtueller Unterklassen, die diese Schnittstellen bereits implementieren, aber ich denke, das würde den Rahmen dieser Frage sprengen. Die anderen hier gezeigten Methoden müssten diese Methode mit dem anpassen
abc
Moduls zu tun.Fazit
Wir haben gezeigt, dass beim Erstellen einer abstrakten Basisklasse Schnittstellen für benutzerdefinierte Objekte in Python definiert werden.
quelle
Python> = 2.6 hat abstrakte Basisklassen .
Es gibt auch das Zope Interface- Modul, das von Projekten außerhalb von zope wie Twisted verwendet wird. Ich bin nicht wirklich vertraut mit ihm, aber es gibt eine Wiki - Seite hier Das könnte helfen.
Im Allgemeinen benötigen Sie kein Konzept für abstrakte Klassen oder Schnittstellen in Python (bearbeitet - Einzelheiten finden Sie in der Antwort von S.Lott).
quelle
Python hat keines der beiden Konzepte.
Es verwendet Enten-Typisierung, wodurch keine Schnittstellen mehr benötigt werden (zumindest für den Computer :-))
Python <= 2.5: Basisklassen existieren offensichtlich, aber es gibt keine explizite Möglichkeit, eine Methode als "rein virtuell" zu markieren, sodass die Klasse nicht wirklich abstrakt ist.
Python> = 2.6: Abstrakte Basisklassen tun exist ( http://docs.python.org/library/abc.html ). Außerdem können Sie Methoden angeben, die in Unterklassen implementiert werden müssen. Ich mag die Syntax nicht sehr, aber die Funktion ist da. Meistens ist es wahrscheinlich besser, die Ententypisierung von der Client-Seite "using" aus zu verwenden.
quelle
Einfacher zu erklären: Eine Benutzeroberfläche ähnelt einer leeren Muffinform. Es ist eine Klassendatei mit einer Reihe von Methodendefinitionen, die keinen Code enthalten.
Eine abstrakte Klasse ist dasselbe, aber nicht alle Funktionen müssen leer sein. Einige können Code haben. Es ist nicht streng leer.
Warum differenzieren: Es gibt keinen großen praktischen Unterschied in Python, aber auf der Planungsebene für ein großes Projekt könnte es üblicher sein, über Schnittstellen zu sprechen, da es keinen Code gibt. Besonders wenn Sie mit Java-Programmierern arbeiten, die an den Begriff gewöhnt sind.
quelle
Im Allgemeinen werden Schnittstellen nur in Sprachen verwendet, die das Klassenmodell der Einzelvererbung verwenden. In diesen Sprachen mit einfacher Vererbung werden normalerweise Schnittstellen verwendet, wenn eine Klasse eine bestimmte Methode oder einen bestimmten Satz von Methoden verwenden könnte. Auch in diesen Einzelvererbungssprachen werden abstrakte Klassen verwendet, um entweder Klassenvariablen zusätzlich zu keiner oder mehreren Methoden zu definieren oder um das Einzelvererbungsmodell zu nutzen, um den Bereich von Klassen zu begrenzen, die eine Reihe von Methoden verwenden könnten.
Sprachen, die das Mehrfachvererbungsmodell unterstützen, verwenden normalerweise nur Klassen oder abstrakte Basisklassen und keine Schnittstellen. Da Python Mehrfachvererbung unterstützt, werden keine Schnittstellen verwendet, und Sie möchten Basisklassen oder abstrakte Basisklassen verwenden.
http://docs.python.org/library/abc.html
quelle
Abstrakte Klassen sind Klassen, die eine oder mehrere abstrakte Methoden enthalten. Abstrakte Klassen können neben abstrakten Methoden auch statische, Klassen- und Instanzmethoden haben. Im Falle einer Schnittstelle gibt es jedoch nur abstrakte Methoden, keine anderen. Daher ist es nicht obligatorisch, eine abstrakte Klasse zu erben, aber es ist obligatorisch, eine Schnittstelle zu erben.
quelle
Der Vollständigkeit halber sollten wir PEP3119 erwähnen, in dem ABC eingeführt und mit Schnittstellen verglichen wurde, sowie den ursprünglichen Kommentar von Talin .
Die abstrakte Klasse ist keine perfekte Schnittstelle:
Aber wenn Sie darüber nachdenken, es auf Ihre eigene Weise zu schreiben:
Sie werden schnell feststellen, dass Sie das Rad erfinden, um es irgendwann zu erreichen
abc.ABCMeta
abc.ABCMeta
wurde als nützliche Ergänzung der fehlenden Schnittstellenfunktionalität vorgeschlagen, und das ist in einer Sprache wie Python fair genug.Sicherlich konnte es beim Schreiben von Version 3 und beim Hinzufügen einer neuen Syntax und eines unveränderlichen Schnittstellenkonzepts besser verbessert werden ...
Fazit:
quelle