Antworten:
Ein Mixin wird normalerweise mit Mehrfachvererbung verwendet. In diesem Sinne gibt es also "keinen Unterschied".
Das Detail ist, dass ein Mixin als eigenständiges Objekt selten nützlich ist.
Angenommen, Sie haben ein Mixin mit dem Namen "ColorAndDimension", das eine Farbeigenschaft sowie Breite und Höhe hinzufügt.
Jetzt können Sie ColorAndDimension beispielsweise zu einer Shape-Klasse, einer Sprite-Klasse, einer Car-Klasse usw. hinzufügen. Alle haben dieselbe Schnittstelle (z. B. get / setColor, get / setHeight / Width usw.).
Im generischen Fall ist ein Mixin also eine Vererbung. Sie können jedoch argumentieren, dass es auf die Rolle der Klasse in der Gesamtdomäne ankommt, ob ein Mixin eine "primäre" Klasse oder einfach ein Mixin ist.
Bearbeiten - nur zur Verdeutlichung.
Ja, ein Mixin kann im heutigen modernen Jargon als Schnittstelle mit einer zugehörigen Implementierung betrachtet werden. Es ist wirklich nur eine einfache, alte, alltägliche Mehrfachvererbung unter Verwendung einer einfachen, alten, alltäglichen Klasse. Es ist einfach eine spezifische Anwendung von MI. Die meisten Sprachen geben einem Mixin keinen besonderen Status. Es ist nur eine Klasse, die entworfen wurde, um "eingemischt" zu werden, anstatt eigenständig verwendet zu werden.
Was ist der Unterschied zwischen einem Mixin und einer Vererbung?
Ein Mix-In ist eine Basisklasse, von der Sie erben können, um zusätzliche Funktionen bereitzustellen. Pseudocode-Beispiel:
class Mixin:
def complex_method(self):
return complex_functionality(self)
Der Name "Mix-In" gibt an, dass es mit anderem Code gemischt werden soll. Die Schlussfolgerung ist daher, dass Sie die Mix-In-Klasse nicht alleine instanziieren würden. Das folgende Objekt hat keine Daten und es macht keinen Sinn, es zu instanziieren, um complex_method aufzurufen. (In diesem Fall können Sie auch einfach eine Funktion anstelle einer Klasse definieren.)
>>> obj = Mixin()
Häufig wird das Mix-In mit anderen Basisklassen verwendet.
Daher sind Mixins eine Teilmenge oder ein Sonderfall der Vererbung.
Die Verwendung eines Mix-Ins gegenüber einer einzelnen Vererbung hat den Vorteil, dass Sie Code für die Funktionalität einmal schreiben und dann dieselbe Funktionalität in mehreren verschiedenen Klassen verwenden können. Der Nachteil besteht darin, dass Sie möglicherweise an anderen Stellen als dort, wo sie verwendet werden, nach dieser Funktionalität suchen müssen. Daher ist es gut, diesen Nachteil zu verringern, indem Sie sie in der Nähe halten.
Ich persönlich habe ein Mix-In gefunden, das für die Verwendung über eine einzelne Vererbung erforderlich ist, wenn wir viele ähnliche Codes nicht testen, aber die Testfälle werden basierend auf ihrer Vererbung eines Basisfalls instanziiert und die einzige Möglichkeit, den Code nahe zu halten Hand (und im selben Modul) muss, ohne mit Abdeckungsnummern herumzuspielen, vom Objekt erben und die untergeordneten Fälle sowohl von der universellen Testfallbasis als auch von der benutzerdefinierten Basis erben lassen, die nur für sie gilt.
Beide sind eine Form der übergeordneten Klasse, die nicht instanziiert werden soll.
Ein Mixin bietet Funktionen, kann diese jedoch nicht direkt verwenden. Ein Benutzer soll es über eine (Unter-) Klasse verwenden.
Eine abstrakte Basisklasse bietet eine Schnittstelle, jedoch ohne verwendbare Funktionalität. Ein Benutzer soll die von der Schnittstelle aufgerufene Funktionalität erstellen.
class Abstraction(metaclass=abc.ABCMeta):
@abc.abstractmethod
def complex_method(self):
return complex_functionality(self)
Hier wird verhindert, dass Sie dieses Objekt instanziieren, da eine Unterklasse erforderlich ist, um die Funktionalität mit einer konkreten Methode zu implementieren (obwohl Sie auf die Funktionalität innerhalb von zugreifen können super()
):
>>> obj = Abstraction()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Abstraction with
abstract methods complex_method
In Python sind einige Klassen im abc
Modul Beispiele für übergeordnete Klassen, die sowohl Funktionen durch Vererbung als auch abstrakte Schnittstellen bereitstellen, die von der Unterklasse implementiert werden müssen. Diese Ideen schließen sich nicht gegenseitig aus.
Einfach ausgedrückt ist ein Mix-In nur eine Basisklasse, die Sie nicht selbst instanziieren würden, und wird normalerweise als sekundäre Basisklasse bei Mehrfachvererbung verwendet.
Mix-In ist ein spezifischer, eingeschränkter Fall von (Mehrfach-) Vererbung, der für Implementierungszwecke verwendet wird. Einige Sprachen (z. B. Ruby) unterstützen dies, ohne die allgemeine Mehrfachvererbung zu unterstützen.
Mixin ist ein abstraktes Konzept und alles, was seine Anforderungen erfüllt, kann als Mixin betrachtet werden.
Hier ist eine Definition aus Wikipedia.
In objektorientierten Programmiersprachen ist ein Mixin eine Klasse, die Methoden zur Verwendung durch andere Klassen enthält, ohne die übergeordnete Klasse dieser anderen Klassen sein zu müssen. Wie diese anderen Klassen Zugriff auf die Methoden des Mixins erhalten, hängt von der Sprache ab. Mixins werden manchmal als "enthalten" und nicht als "geerbt" beschrieben.
Kurz gesagt, der Hauptunterschied zu einer Vererbung besteht darin, dass Mix-Ins KEINE "is-a" -Beziehung wie bei der Vererbung haben müssen.
Aus Sicht der Implementierung können Sie es als Schnittstelle zu Implementierungen betrachten. Beispielsweise könnte eine abstrakte Klasse in Java als Mixin betrachtet werden, wenn Java Mehrfachvererbung unterstützt.
"Ein Mixin ist ein Fragment einer Klasse in dem Sinne, dass es mit anderen Klassen oder Mixins zusammengesetzt werden soll." -DDJ
Ein Mixin ist ein Klassen- oder Codefragment, das nicht für die eigenständige Verwendung vorgesehen ist, sondern in einer anderen Klasse verwendet werden soll. Entweder als Elementfeld / Variable oder als Codesegment. Ich bin dem späteren am meisten ausgesetzt. Es ist ein bisschen besser als das Einfügen von Boilerplate-Code.
Hier ist ein großartiger DDJ-Artikel, der das Thema vorstellt.
Das Half-Life 2 / "Source" SDK ist ein großartiges Beispiel für C ++ - Mixins. In dieser Umgebung definieren Makros beträchtliche Codeblöcke, die hinzugefügt werden können, um der Klasse einen bestimmten "Geschmack" oder eine bestimmte Funktion zu verleihen.
Schauen Sie sich das Beispiel des Quell-Wikis an: Erstellen einer logischen Entität . Im Beispielcode kann das Makro DECLARE_CLASS als Mixin betrachtet werden. Das Quell-SDK verwendet Mixins in großem Umfang, um den Datenzugriffscode zu standardisieren und Entitäten Verhaltensweisen zuzuweisen.
Bei Mehrfachvererbung kann eine neue Klasse aus mehreren Oberklassen bestehen. Sie können nur Methoden aufrufen, die in einer der Oberklassen definiert sind.
Auf der anderen Seite ist Mixin eine abstrakte Unterklasse, die verwendet werden kann, um den Beavior einer Vielzahl von Elternklassen zu spezialisieren. Mixins können beispielsweise eine Methode aufrufen sayHello(): String
, obwohl sie eine solche Methode nicht definieren.
mixin M {
name: String
defmethod greetings() { print sayHello() + " " + name}
}
Wie Sie sehen, können Sie anrufen sayHello()
, obwohl es nirgendwo definiert ist. Wenn Sie das Mixin M
zur Klasse hinzufügen C
, C
sollte das die sayHello()
Methode bereitstellen .
Ich denke, es ist wichtig anzumerken, dass Mixin keine Vererbung impliziert . Laut Wikipedia ist ein Mixin :
In objektorientierten Programmiersprachen ist ein Mixin eine Klasse, die Methoden zur Verwendung durch andere Klassen enthält, ohne die übergeordnete Klasse dieser anderen Klassen sein zu müssen. Wie diese anderen Klassen Zugriff auf die Methoden des Mixins erhalten, hängt von der Sprache ab. Mixins werden manchmal als "enthalten" und nicht als "geerbt" beschrieben.
Insbesondere in einer Sprache wie Perl können Mixins mithilfe des Exporter-Moduls hinzugefügt werden:
package Mixins;
use Exporter qw(import);
our @EXPORT_OK = qw(pity);
# assumes it will be mixed-in to a class with a _who_do_i_pity method
sub pity {
my ($self) = @_;
printf("I pity %s\n", $self->_who_do_i_pity('da foo'));
}
Was in jedes Modul eingemischt werden kann, das jeweils eine oder mehrere Methoden enthält:
package MrT
use Mixins qw(pity);
sub new {
return bless({}, shift);
}
sub _who_do_i_pity {
return 'da foo!'
}
Dann kann in Ihrem MrT
Modul folgendermaßen verwendet werden:
use MrT;
MrT->new()->pity();
Ich weiß, dass es ein absurdes Beispiel ist, aber es bringt den Punkt auf den Punkt ...
tl; dr
Mixin und Mehrfachvererbung haben dieselbe Form. Aber haben unterschiedliche Semantik: Mixin hat die Grundklassen für die Funktionsimplementierung. Für die Vererbung stellen Basisklassen eine Schnittstelle bereit und die Unterklasse hat die Implementierung.
Trotzdem wird die Zusammensetzung dem Mischen von IMO vorgezogen