Ich habe den größten Teil meiner Recherchen zu BabelJS und MDN (das überhaupt keine Informationen enthält) durchgeführt. Sie können mir jedoch gerne mitteilen, ob ich nicht sorgfältig genug nach weiteren Informationen zur ES6-Spezifikation gesucht habe.
Ich frage mich, ob ES6 die Mehrfachvererbung auf dieselbe Weise unterstützt wie andere Sprachen vom Typ Ente. Kann ich zum Beispiel so etwas tun:
class Example extends ClassOne, ClassTwo {
constructor() {
}
}
mehrere Klassen auf die neue Klasse erweitern? Wenn ja, bevorzugt der Interpreter Methoden / Eigenschaften von ClassTwo gegenüber ClassOne?
Antworten:
Ein Objekt kann nur einen Prototyp haben. Das Erben von zwei Klassen kann durch Erstellen eines übergeordneten Objekts als Kombination von zwei übergeordneten Prototypen erfolgen.
Die Syntax für die Unterklasse ermöglicht dies in der Deklaration, da die rechte Seite der
extends
Klausel ein beliebiger Ausdruck sein kann. Auf diese Weise können Sie eine Funktion schreiben, die Prototypen nach beliebigen Kriterien kombiniert, und diese Funktion in der Klassendeklaration aufrufen.quelle
__proto__
Link zu setzen, um die Requisitensuche an das richtige Objekt weiterzuleiten. Ich habe es versucht, aber noch nie zum__proto__
selbst eine veraltete Funktion ist. Es spiegelt die interne Prototypverbindung wider, aber es ist nicht wirklich die interne Prototypverbindung.class Foo extends new MultiClass(Bar, Baz, One, Two) { ... }
. Die Methoden und Eigenschaften des letzten übergebenen Konstruktorsnew MultiClass
haben höchste Priorität. Sie werden lediglich in den neuen Prototyp eingemischt. Ich denke, es gibt eine noch bessere Lösung, wenn sie mit ES6 Proxies erneut implementiert wird, aber es gibt noch nicht genug native Unterstützung dafür.Überprüfen Sie mein Beispiel unten,
super
Methode funktioniert wie erwartet. Mit ein paar Tricksinstanceof
funktioniert es sogar (meistens):Wird ausgedruckt
Link zum Herumspielen
quelle
(B||Object)
.F extends (B||Object)
stattdessenF extends B(Object)
, wird das B-Mixin so erweitert, wie es ist (als Funktion), sodass F nur den Standardfunktionsprototyp erweitert, da B nie ausgeführt wurde. Mit verwendenF extends B(Object)
wir tatsächlich die B-Funktion und F erweitert 'was auch immer' B-Funktion zurückgibt. In diesem Fall ist es die B-Klasse, die in der B-Funktion definiert ist ... kleiner Hack, um die Klassennamen richtig zu halten.const B = (B = Object) => class extends B {
und dannclass F extends B() {
für eine schönere Verwendung zu verwenden, aber hässlicher Hack Kappaconst B = (B) => class extends (B||Object) {
würde Sie ersetzeninst5 = new (B(Object)); // instance only B, ugly format
mitinst5 = new (B());
, oder vielleicht ich falsch verstehen den Kontext ...console.log('from B -> inside instance of B: ${this instanceof B}');
Hexe als scheitertRight-hand side of 'instanceof' is not an object
. Die Verwendungconst B = (B = Object) => class extends B {
wie zuvor erwähnt besteht die Testinstanz und bietet Ihnen auch dieinst5 = new (B());
Verwendung, wenn Sie dies wünschen.Für die Implementierung von Sergio Carneiro und Jon müssen Sie eine Initialisierungsfunktion für alle bis auf eine Klasse definieren. Hier ist eine modifizierte Version der Aggregationsfunktion, die stattdessen Standardparameter in den Konstruktoren verwendet. Enthalten sind auch einige Kommentare von mir.
Hier ist eine kleine Demo:
Diese Aggregationsfunktion bevorzugt Eigenschaften und Methoden einer Klasse, die später in der Klassenliste angezeigt werden.
quelle
Component
, funktioniert es nicht. Nur zu Ihrer Information an alle anderen, die es zu diesem Zweck gewollt haben könnten.Justin Fagnani beschreibt einen sehr sauberen (imho) Weg , um mehrere Klassen in einem mit der Tatsache zu komponieren , dass in ES2015 können Klassen mit Klasse erstellt werden Ausdrücke .
Ausdrücke gegen Erklärungen
Grundsätzlich können Sie eine Funktion mit einem Ausdruck erstellen:
Sie können dasselbe mit Klassen tun:
Der Ausdruck wird zur Laufzeit ausgewertet, wenn der Code ausgeführt wird, während zuvor eine Deklaration ausgeführt wird.
Verwenden von Klassenausdrücken zum Erstellen von Mixins
Mit dieser Option können Sie eine Funktion erstellen, die nur dann dynamisch eine Klasse erstellt, wenn die Funktion aufgerufen wird:
Das Coole daran ist, dass Sie die gesamte Klasse im Voraus definieren und nur entscheiden können, welche Klasse bis zum Aufruf der Funktion erweitert werden soll:
Wenn Sie mehrere Klassen miteinander mischen möchten, da ES6-Klassen nur eine einzige Vererbung unterstützen, müssen Sie eine Klassenkette erstellen, die alle Klassen enthält, die Sie zusammen mischen möchten. Angenommen, Sie möchten eine Klasse C erstellen, die sowohl A als auch B erweitert. Sie können dies tun:
Das Problem dabei ist, dass es sehr statisch ist. Wenn Sie später entscheiden, dass Sie eine Klasse D erstellen möchten, die B, aber nicht A erweitert, haben Sie ein Problem.
Mit einigen cleveren Tricks, bei denen Klassen Ausdrücke sein können, können Sie dies lösen, indem Sie A und B nicht direkt als Klassen, sondern als Klassenfabriken erstellen (der Kürze halber mit Pfeilfunktionen):
Beachten Sie, dass wir erst im letzten Moment entscheiden, welche Klassen in die Hierarchie aufgenommen werden sollen.
quelle
Dies ist mit der Funktionsweise der prototypischen Vererbung nicht wirklich möglich. Schauen wir uns an, wie geerbte Requisiten in js funktionieren
Mal sehen, was passiert, wenn Sie auf eine Requisite zugreifen, die es nicht gibt:
Sie können Mixins verwenden , um einige dieser Funktionen zu erhalten, aber Sie werden keine späte Bindung erhalten:
vs.
quelle
Ich habe mir diese Lösung ausgedacht:
Verwendung:
Solange Sie diesen Trick mit Ihren speziell geschriebenen Klassen machen, kann er verkettet werden. Aber wenn Sie eine nicht so geschriebene Funktion / Klasse erweitern möchten, haben Sie keine Chance, die Schleife fortzusetzen.
funktioniert für mich in Knoten v5.4.1 mit dem Flag --harmony
quelle
Auf der Seite es6-features.org/#ClassInheritanceFromExpressions kann eine Aggregationsfunktion geschrieben werden, um Mehrfachvererbung zu ermöglichen:
Dies ist jedoch bereits in Bibliotheken wie der Aggregation vorgesehen .
quelle
Verwenden Sie Mixins für ES6 Multiple Inheritence.
quelle
one class inherits from 2 or more unrelated classes
? Was Ihr Beispiel zeigt, ist eine Klasse, die von 2 erbt, aber verwandte Klassen. Dies ist eine Einzelvererbung, keine Mehrfachvererbung.classTwo
. Ohne ein echtes Klassenkonzept hat JS sowieso keine strukturelle Vererbung. Auf Anhieb kann ich mir kein JS-Szenario vorstellen, in dem sich Mixins anders verhalten als erwartet, wenn man sie als MI aus der wahren OO-Welt betrachtet (abgesehen von der definierten 'Super'-Kette). Vielleicht kann eine Person, die besser informiert ist als ich, eine liefern.Nun, Object.assign bietet Ihnen die Möglichkeit, etwas Nahes zu tun, wenn auch ein bisschen mehr wie Komposition mit ES6-Klassen.
Ich habe nicht gesehen, dass dies irgendwo verwendet wird, aber es ist tatsächlich ziemlich nützlich. Sie können
function shark(){}
anstelle von Klasse verwenden, aber es gibt Vorteile, stattdessen Klasse zu verwenden.Ich glaube, das einzige, was sich bei der Vererbung mit
extend
Schlüsselwörtern unterscheidet, ist, dass die Funktion nicht nur aufprototype
dem Objekt, sondern auch auf dem Objekt selbst lebt .Wenn Sie dies tun, verfügt
new Shark()
dasshark
Erstellte über einebite
Methode, während nur der Prototyp über eineeat
Methode verfügtquelle
Es gibt keine einfache Möglichkeit, eine Vererbung mehrerer Klassen durchzuführen. Ich folge der Kombination von Assoziation und Vererbung, um diese Art von Verhalten zu erreichen.
Hoffe das ist hilfreich.
quelle
Diese ES6-Lösung hat bei mir funktioniert:
multiple-inheritance.js
main.js
Ausbeuten auf der Browserkonsole:
quelle
Ich habe eine halbe Woche damit verbracht, dies selbst herauszufinden, und einen ganzen Artikel darüber geschrieben, https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS , und hoffe, dass es einigen von Ihnen hilft.
Kurz gesagt, wie MI in JavaScript implementiert werden kann:
Und hier ist specialize_with () einzeilig:
Weitere Informationen finden Sie unter https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS .
quelle
In Javascript können Sie einer Klasse (Konstruktorfunktion) nicht 2 verschiedene Prototypobjekte geben. Da die Vererbung in Javascript mit dem Prototyp zusammenarbeitet, können Sie nicht mehr als 1 Vererbung für eine Klasse verwenden, aber Sie können die Eigenschaft des Prototype-Objekts und dieser Haupteigenschaft aggregieren und verbinden Innerhalb einer Klasse manuell mit Refactoring dieser übergeordneten Klassen und als nächstes erweitert diese neue Version und verbundene Klasse zu Ihrer Zielklasse haben Code für Ihre Frage:
quelle
Meine Antwort scheint weniger Code zu sein und funktioniert bei mir:
quelle
Verwenden Sie Extent mit benutzerdefinierter Funktion, um die Mehrfachvererbung mit es6 zu verarbeiten
quelle
Ich werde auch meine Lösung hinzufügen - ich fand sie für mich selbst am freundlichsten, was ich in diesem Thread gelesen habe.
Sie können es dann so verwenden:
quelle
Als Proof of Concept habe ich folgende Funktion ausgeführt. Es nimmt eine Liste von Klassen und setzt sie zu einer neuen Klasse zusammen (der letzte Prototyp gewinnt, damit es keine Konflikte gibt). Beim Erstellen einer zusammengesetzten Funktion kann der Benutzer alle Originalkonstruktoren verwenden [ sic! ] oder ihre eigenen übergeben. Dies war die größte Herausforderung dieses Experiments: eine Beschreibung zu erstellen, was der Konstruktor tun sollte. Das Kopieren von Methoden in einen Prototyp ist kein Problem, sondern die beabsichtigte Logik eines neu zusammengesetzten Objekts. Oder sollte es vielleicht konstruktorlos sein? Soweit ich weiß, findet es in Python den passenden Konstruktor, aber Funktionen in JS sind akzeptabler, daher kann man fast alles an eine Funktion übergeben, und von der Signatur ist es nicht klar.
Ich denke nicht, dass es optimiert ist, aber der Zweck war es, Möglichkeiten zu erkunden.
instanceof
wird sich nicht wie erwartet verhalten, was, denke ich, ein Mist ist, da klassenorientierte Entwickler dies gerne als Werkzeug verwenden.Vielleicht hat JavaScript es einfach nicht.
Ursprünglich hier gepostet (gist.github.com).
quelle
https://www.npmjs.com/package/ts-mixer
Mit der besten TS-Unterstützung und vielen anderen nützlichen Funktionen!
quelle
Hier ist eine großartige / wirklich beschissene Möglichkeit, mehrere Klassen zu erweitern. Ich benutze ein paar Funktionen, die Babel in meinen transpilierten Code eingefügt hat. Die Funktion erstellt eine neue Klasse, die Klasse1 erbt, und Klasse1 erbt Klasse2 usw. Es hat seine Probleme, aber eine lustige Idee.
quelle