J'ai fait la plupart de mes recherches à ce sujet sur BabelJS et sur MDN (qui ne contient aucune information), mais n'hésitez pas à me dire si je n'ai pas été assez prudent en cherchant plus d'informations sur la spécification ES6.
Je me demande si ES6 prend en charge l'héritage multiple de la même manière que les autres langages de type canard. Par exemple, puis-je faire quelque chose comme:
class Example extends ClassOne, ClassTwo {
constructor() {
}
}
étendre plusieurs classes à la nouvelle classe? Si tel est le cas, l'interpréteur préférera-t-il les méthodes / propriétés de ClassTwo à ClassOne?
Réponses:
Un objet ne peut avoir qu'un seul prototype. L'héritage de deux classes peut être effectué en créant un objet parent sous la forme d'une combinaison de deux prototypes parents.
La syntaxe du sous-classement permet de faire cela dans la déclaration, puisque le côté droit de la
extends
clause peut être n'importe quelle expression. Ainsi, vous pouvez écrire une fonction qui combine des prototypes selon les critères de votre choix et appeler cette fonction dans la déclaration de classe.la source
__proto__
lien pour transférer la recherche d'accessoires vers le bon objet? J'ai essayé mais je n'ai jamais réussi à le faire fonctionner__proto__
lui - même est une fonctionnalité obsolète. Cela reflète le lien interne du prototype, mais ce n'est pas vraiment le lien interne du prototype.class Foo extends new MultiClass(Bar, Baz, One, Two) { ... }
. Les méthodes et propriétés du dernier constructeur passées pournew MultiClass
avoir la priorité la plus élevée, elles sont simplement mélangées dans le nouveau prototype. Je pense qu'une solution encore meilleure existe si elle est réimplémentée à l'aide de proxys ES6, mais il n'y a pas encore assez de support natif pour cela.Vérifiez mon exemple ci-dessous, la
super
méthode fonctionne comme prévu. L'utilisation de quelques astucesinstanceof
fonctionne même (la plupart du temps):Imprimera
Lien vers violon
la source
(B||Object)
.F extends (B||Object)
au lieu deF extends B(Object)
, il étendra le mixin B tel qu'il (en tant que fonction), donc F étendra uniquement le prototype Function par défaut puisque B n'a jamais été exécuté. En utilisant,F extends B(Object)
nous exécutons en fait la fonction B et F étendra `` tout '' la fonction B renvoie, dans ce cas, c'est la classe B définie à l'intérieur de la fonction B ... petit hack pour garder le nom de classe correct.const B = (B = Object) => class extends B {
, puis les utiliserclass F extends B() {
pour une utilisation plus jolie, mais plus moche, hack Kappaconst B = (B) => class extends (B||Object) {
vous laisserait remplacerinst5 = new (B(Object)); // instance only B, ugly format
parinst5 = new (B());
, ou peut-être que je comprends mal le contexte ...console.log('from B -> inside instance of B: ${this instanceof B}');
sorcière échoueRight-hand side of 'instanceof' is not an object
. L'utilisationconst B = (B = Object) => class extends B {
comme mentionné précédemment passera le test instanceof et vous fournira également l'inst5 = new (B());
utilisation si vous le souhaitez.L'implémentation de Sergio Carneiro et Jon vous oblige à définir une fonction d'initialisation pour toutes les classes sauf une. Voici une version modifiée de la fonction d'agrégation, qui utilise à la place des paramètres par défaut dans les constructeurs. J'inclus également quelques commentaires de ma part.
Voici une petite démo:
Cette fonction d'agrégation préférera les propriétés et les méthodes d'une classe qui apparaissent plus tard dans la liste des classes.
la source
Component
, cela ne fonctionne pas. juste FYI à toute autre personne qui aurait pu le vouloir à cette fin.Justin Fagnani décrit une manière très propre (à mon humble avis) de composer plusieurs classes en une en utilisant le fait que dans ES2015, les classes peuvent être créées avec des expressions de classe .
Expressions vs déclarations
En gros, tout comme vous pouvez créer une fonction avec une expression:
vous pouvez faire la même chose avec les classes:
L'expression est évaluée à l'exécution, lorsque le code s'exécute, alors qu'une déclaration est exécutée au préalable.
Utilisation d'expressions de classe pour créer des mixins
Vous pouvez l'utiliser pour créer une fonction qui crée dynamiquement une classe uniquement lorsque la fonction est appelée:
Ce qui est cool, c'est que vous pouvez définir la classe entière à l'avance et ne décider que de la classe à étendre au moment où vous appelez la fonction:
Si vous souhaitez mélanger plusieurs classes ensemble, étant donné que les classes ES6 ne prennent en charge qu'un seul héritage, vous devez créer une chaîne de classes contenant toutes les classes que vous souhaitez mélanger. Alors disons que vous voulez créer une classe C qui étend à la fois A et B, vous pouvez faire ceci:
Le problème, c'est que c'est très statique. Si vous décidez par la suite que vous voulez créer une classe D qui étend B mais pas A, vous avez un problème.
Mais avec une astuce intelligente utilisant le fait que les classes peuvent être des expressions, vous pouvez résoudre ce problème en créant A et B non pas directement en tant que classes, mais en tant que fabriques de classes (en utilisant les fonctions fléchées par souci de concision):
Remarquez que nous ne décidons qu'au dernier moment quelles classes inclure dans la hiérarchie.
la source
Ce n'est pas vraiment possible avec le fonctionnement de l'héritage prototypique. Jetons un coup d'œil au fonctionnement des accessoires hérités dans js
voyons ce qui se passe lorsque vous accédez à un accessoire qui n'existe pas:
Vous pouvez utiliser des mixins pour obtenir certaines de ces fonctionnalités, mais vous n'obtiendrez pas de liaison tardive:
contre
la source
Je propose ces solutions:
usage:
Tant que vous faites ces trucs avec vos classes écrites sur mesure, vous pouvez les enchaîner. mais nous dès que vous voulez étendre une fonction / classe écrite pas comme ça - vous n'aurez aucune chance de continuer la boucle.
fonctionne pour moi dans le nœud v5.4.1 avec le drapeau --harmony
la source
utilisez Mixins pour l'héritage multiple ES6.
la source
one class inherits from 2 or more unrelated classes
? Ce que montre votre exemple est une classe héritant de 2, mais des classes liées. Il s'agit d'un héritage unique et non d'un héritage multiple.classTwo
. Faute d'un véritable concept de classe, JS n'a de toute façon aucun héritage structurel . Offhand, je ne peux pas concevoir un scénario JS où les mixins se comportent différemment de ce à quoi vous vous attendez en les conceptualisant comme MI du véritable monde OO (à part la «super» chaîne définie); peut-être qu'une personne plus informée que moi pourra en fournir une.Depuis la page es6-features.org/#ClassInheritanceFromExpressions , il est possible d'écrire une fonction d'agrégation pour permettre l'héritage multiple:
Mais cela est déjà fourni dans les bibliothèques comme l' agrégation .
la source
Eh bien, Object.assign vous donne la possibilité de faire quelque chose de proche, mais un peu plus comme une composition avec des classes ES6.
Je n'ai vu cela utilisé nulle part, mais c'est en fait assez utile. Vous pouvez utiliser à la
function shark(){}
place de la classe, mais il y a des avantages à utiliser la classe à la place.Je pense que la seule chose différente avec l'héritage avec
extend
mot-clé est que la fonction ne vit pas seulement surprototype
l'objet mais aussi sur l'objet lui-même.Ainsi maintenant quand vous faites
new Shark()
leshark
créé a unebite
méthode, alors que seul son prototype a uneeat
méthodela source
Il n'y a pas de moyen simple de faire l'héritage de plusieurs classes. Je suis la combinaison de l'association et de l'héritage pour réaliser ce genre de comportement.
J'espère que cela vous sera utile.
la source
Cette solution ES6 a fonctionné pour moi:
multiple-inheritance.js
main.js
Rendements sur la console du navigateur:
la source
J'ai passé une demi-semaine à essayer de comprendre cela moi-même et j'ai écrit un article complet à ce sujet, https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS , et j'espère que cela aidera certains d'entre vous.
En bref, voici comment MI peut être implémenté en JavaScript:
Et voici specialize_with () one-liner:
Encore une fois, veuillez consulter https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS .
la source
en javascript, vous ne pouvez pas donner à une classe (fonction constructeur) 2 objets prototypes différents et parce que l'héritage en javascript fonctionne avec un prototype, vous ne pouvez donc pas utiliser plus d'un héritage pour une classe, mais vous pouvez agréger et joindre la propriété de l'objet Prototype et cette propriété principale à l'intérieur d'une classe manuellement avec la refactorisation des classes parentes et ensuite étend cette nouvelle version et la classe jointe à votre classe cible ont du code pour votre question:
la source
Ma réponse semble être moins de code et cela fonctionne pour moi:
la source
utiliser l'extension avec une fonction personnalisée pour gérer l'héritage multiple avec es6
la source
J'ajouterai également ma solution - je l'ai trouvée la plus conviviale pour moi d'après ce que j'ai lu dans ce fil.
Vous pouvez alors l'utiliser comme ceci:
la source
Comme preuve de concept, j'ai effectué la fonction suivante. Il prend une liste de classes et les compose dans une nouvelle classe (le dernier prototype gagne donc il n'y a pas de conflits). Lors de la création d'une fonction composée, l'utilisateur peut choisir d'utiliser tous les constructeurs d'origine [ sic! ] ou passer le leur. C'était le plus grand défi de cette expérience: trouver une description de ce que le constructeur devrait faire. La copie de méthodes dans un prototype n'est pas un problème, mais quelle est la logique voulue pour l'objet nouvellement composé. Ou peut-être que cela devrait être sans constructeur? En Python, d'après ce que je sais, il trouve le constructeur correspondant, mais les fonctions dans JS sont plus acceptables, par conséquent, on peut passer à une fonction à peu près tout et à partir de la signature, ce ne sera pas clair.
Je ne pense pas que ce soit optimisé mais le but était d'explorer les possibilités.
instanceof
ne se comportera pas comme prévu, ce qui, je suppose, est une déception, car les développeurs axés sur les classes aiment l'utiliser comme un outil.Peut-être que JavaScript ne l'a tout simplement pas.
Publié à l' origine ici (gist.github.com).
la source
https://www.npmjs.com/package/ts-mixer
Avec le meilleur support TS et de nombreuses autres fonctionnalités utiles!
la source
Voici une façon géniale / vraiment merdique d'étendre plusieurs classes. J'utilise quelques fonctions que Babel a mises dans mon code transpilé. La fonction crée une nouvelle classe qui hérite de classe1, et classe1 hérite de classe2, et ainsi de suite. Il a ses problèmes, mais une idée amusante.
la source