Vererbung vs Mixins in dynamischen Sprachen?

19

Wann sollten Sie Vererbungsmuster gegenüber Mixins in dynamischen Sprachen bevorzugen?

Mit Mixins meine ich das eigentliche richtige Einmischen, wie das Einfügen von Funktionen und Datenelementen in ein Objekt zur Laufzeit.

Wann würden Sie beispielsweise die prototypische Vererbung anstelle von Mixins verwenden? Um deutlicher zu veranschaulichen, was ich mit mixin meine, gibt es einen Pseudocode:

asCircle(obj) {
  obj.radius = 0
  obj.area = function() {
    return this.radius * this.radius * 3.14
  }

myObject = {}
asCircle(myObject)
myObject.area() // -> 0
Magnus Wolffelt
quelle
2
Mixins sind eher Querschnittsaspekte als direkte Vererbung. Das wird wahrscheinlich einige Anwendungsfälle für Sie definieren.
Asche999
1
Zusammensetzung, jeder :)
OnesimusUnbound

Antworten:

14

Die prototypische Vererbung ist einfach. Es hat einen einzigen Vorteil gegenüber Mixins.

Das heißt, es ist eine Live-Verbindung. Wenn Sie den Prototyp ändern, wird alles, was er erbt, geändert.

Beispiel mit pd

var Circle = {
  constructor: function _constructor() {
    this.radius = 0;
    return this;
  },
  area: function _area() {
    return this.radius * this.radius * Circle.PI
  },
  PI: 3.14
};

var mixedIn = pd.extend({}, Circle).constructor();
var inherited = pd.make(Circle, {}).constructor();

Circle.perimeter = perimeter;

inherited.perimeter(); // wins
mixedIn.perimeter(); // fails

function perimeter() {
  return 2 * this.radius;
}

Wenn Sie also Änderungen am "Interface" -Kreis zur Laufzeit für alle Objekte vornehmen möchten, die dessen Funktionalität "nutzen", übernehmen Sie diese.

Wenn Sie nicht möchten, dass Änderungen übernommen werden, mischen Sie sie ein.

Beachten Sie, dass Mixins auch mehr Zweck haben. Mixins sind Ihr Mechanismus für die mehrfache "Vererbung".

Wenn Sie ein Objekt wollen mehrere „Schnittstellen“ implementieren , dann Sie werden in einigen mischen müssen. Die Sie für prototypische Vererbung ist , die Sie Änderungen während der Laufzeit reflektieren wollen, werden die anderen in gemischt werden.

Raynos
quelle
12

Mein Pferdesinn sagt mir:

  • Wenn etwas über mehrere Objekte oder Klassenhierarchien hinweg nützlich ist, machen Sie es zu einem Mixin
  • Wenn etwas nur in einer einzigen Hierarchie nützlich ist, verwenden Sie die Vererbung

Verwandte Hinweise:

  • Das Wort "nützlich" sollte metaphorisch verstanden werden
  • Für Sprachen ohne Mehrfachvererbung sind Mixins eine gute Alternative
  • PHP 5.4 führt Eigenschaften ein , die sowohl aus Mixins als auch aus Welten mit mehreren Vererbungen stammen
Baumkodierer
quelle
+1, mein Lieblingsbeispiel für "etwas Nützliches über mehrere Objekte oder Klassenhierarchien hinweg" in Ruby ist das Modul Enumerable
David
1
Ich würde sagen, dass Mehrfachvererbung eine (nicht so gute) Alternative zu Mixins sein kann.
Simon Bergot
@ Simon Ich würde sagen, dass Mixins eine (nicht so gute) Alternative zur Mehrfachvererbung sein kann;)
Raynos
Mein Pferdesinn sagte mir das auch. :)
Theringostarrs
9

Verwenden Sie den "Is-a" -Test.

Die Vererbung ist auf den Fall beschränkt, in dem Sie "Unterklasse IST Eine Superklasse" sagen können. Sie sind das Gleiche. "Käse ist ein Milchprodukt".

Mixins sind für alles andere. "Käse kann in einem Sandwich verwendet werden". Käse ist kein Sandwich, aber er spielt beim Sandwiching eine Rolle.

PS. Dies hat nichts mit dynamischen Sprachen zu tun. Jede Mehrfachvererbungssprache mit statischer Kompilierung (dh C ++) hat denselben Entscheidungspunkt.

S.Lott
quelle
Auf jeden Fall haben + 1- statische Sprachen auch Mixins.
DeadMG
Richtig, Mixins können in vielen Sprachen erstellt werden - das war nicht meine Frage. Dynamische Sprachen haben bestimmte Eigenschaften, die Mixins in solchen Sprachen möglicherweise anders und / oder interessanter machen - Raynos wies auf einen Aspekt hin. Darüber hinaus nennen Sie keine konkreten Gründe, warum Sie das IS A-Konzept anstelle des Mixin-Konzepts verwenden sollten.
Magnus Wolffelt,
@MagnusWolffelt: Sie sind das Gleiche. "Käse ist ein Milchprodukt". Das ist die Regel für IS-A. Was soll ich noch sagen?
S.Lott
Meine Frage bezieht sich mehr auf Entwurfsentscheidungen - in welchen Situationen möchten Sie Vererbung und aus welchen Gründen? In dynamischen Sprachen sehe ich neben den von Raynos beschriebenen nur wenige Gründe, Vererbung gegenüber Mixins zu wählen. Die Durchführung der Objekterstellung könnte ein Grund sein.
Magnus Wolffelt
@MagnusWolffelt: "In welchen Situationen möchten Sie Vererbung?" Wenn die beiden Klassen die IS-A-Beziehung erfüllen. "Durchführung der Objekterstellung" ist kein Grund, sich für eine andere zu entscheiden. Die Vererbung macht eine sehr starke Aussage über die beiden Klassen von Objekten. Mixins macht eine schwächere und flexiblere Aussage. Vererbung wird verwendet, wenn die beiden Klassen die Beziehung "IS-A" erfüllen. Was könnte ich noch sagen? Ich kann deine Frage nicht sehr gut verstehen. Können Sie klarstellen, was Sie noch wissen möchten?
S.Lott
0

Nun, das beste Beispiel, das ich Ihnen geben kann, ist ein Schauspieler für ein Spiel, das Vererbung für einige grundlegende Dinge hat, aber Mixins / Plugins für gemeinsame Funktionen verwendet. Die geteilte Funktionalität könnte (direkt aus dem Quellcode!) Sein:

var plugins = {
    SingleVisualEntity : SingleVisualEntity,
    JumpBehaviour      : JumpBehaviour,
    WeaponBehaviour    : WeaponBehaviour,
    RadarBehaviour     : RadarBehaviour,
    EnergyGatherer     : EnergyGatherer,
    LifeBarPlugin      : LifeBarPlugin,
    SelectionPlugin    : SelectionPlugin,
    UpgradePlugin      : UpgradePlugin,
    BrainPlugin        : BrainPlugin,
    PlanetObjectPlugin : PlanetObjectPlugin,
}
Totty.js
quelle