He realizado la mayor parte de mi investigación sobre esto en BabelJS y en MDN (que no tiene ninguna información), pero no dude en decirme si no he sido lo suficientemente cuidadoso para buscar más información sobre la especificación ES6.
Me pregunto si ES6 admite o no la herencia múltiple de la misma manera que otros lenguajes de tipo pato. Por ejemplo, ¿puedo hacer algo como:
class Example extends ClassOne, ClassTwo {
constructor() {
}
}
extender múltiples clases a la nueva clase? Si es así, ¿preferirá el intérprete métodos / propiedades de ClassTwo sobre ClassOne?
Respuestas:
Un objeto solo puede tener un prototipo. La herencia de dos clases se puede hacer creando un objeto primario como una combinación de dos prototipos principales.
La sintaxis para la subclasificación permite hacer eso en la declaración, ya que el lado derecho de la
extends
cláusula puede ser cualquier expresión. Por lo tanto, puede escribir una función que combine prototipos de acuerdo con los criterios que desee y llamar a esa función en la declaración de clase.fuente
__proto__
enlace para reenviar la búsqueda de utilería al objeto correcto? Lo he intentado pero nunca lo he conseguido__proto__
sí mismo es una característica obsoleta. Refleja el enlace prototipo interno, pero no es realmente el enlace prototipo interno.class Foo extends new MultiClass(Bar, Baz, One, Two) { ... }
. Los métodos y propiedades del último constructor pasado paranew MultiClass
tener mayor prioridad, simplemente se mezclan con el nuevo prototipo. Creo que existe una solución aún mejor si se vuelve a implementar usando Proxies ES6, pero todavía no hay suficiente soporte nativo para ello.Consulte mi ejemplo a continuación, el
super
método funciona como se esperaba. Usar algunos trucos inclusoinstanceof
funciona (la mayoría de las veces):Imprimirá
Enlace para violín
fuente
(B||Object)
.F extends (B||Object)
lugar deF extends B(Object)
hacerlo, extenderá el mixin B como lo hace (como una función) de modo que F solo extenderá el prototipo de Función predeterminado ya que B nunca se ejecutó. Al usarloF extends B(Object)
, en realidad estamos ejecutando la función B y F extenderá 'lo que sea' que devuelva la función B, en este caso es la clase B definida dentro de la función B ... pequeño truco para mantener el nombre correcto de la clase.const B = (B = Object) => class extends B {
y luego usarlosclass F extends B() {
para un uso más bonito, pero el hack más feo Kappaconst B = (B) => class extends (B||Object) {
te dejaría reemplazarinst5 = new (B(Object)); // instance only B, ugly format
coninst5 = new (B());
, o tal vez no entiendo el contexto ...console.log('from B -> inside instance of B: ${this instanceof B}');
bruja falle comoRight-hand side of 'instanceof' is not an object
. El usoconst B = (B = Object) => class extends B {
como se mencionó anteriormente pasará la instancia de prueba y también le proporcionará elinst5 = new (B());
uso si lo desea.La implementación de Sergio Carneiro y Jon requiere que defina una función inicializadora para todas las clases menos una. Aquí hay una versión modificada de la función de agregación, que utiliza parámetros predeterminados en los constructores. También se incluyen algunos comentarios míos.
Aquí hay una pequeña demostración:
Esta función de agregación preferirá las propiedades y métodos de una clase que aparecen más adelante en la lista de clases.
fuente
Component
, no funciona. solo para tu información a cualquiera que lo haya querido para este propósito.Justin Fagnani describe una forma muy limpia (en mi humilde opinión) de componer varias clases en una utilizando el hecho de que en ES2015, las clases se pueden crear con expresiones de clase .
Expresiones vs declaraciones
Básicamente, al igual que puedes crear una función con una expresión:
Puedes hacer lo mismo con las clases:
La expresión se evalúa en tiempo de ejecución, cuando se ejecuta el código, mientras que una declaración se ejecuta de antemano.
Usando expresiones de clase para crear mixins
Puede usar esto para crear una función que crea dinámicamente una clase solo cuando se llama a la función:
Lo bueno de esto es que puedes definir toda la clase de antemano y solo decidir en qué clase se extenderá para cuando llames a la función:
Si desea mezclar varias clases, ya que las clases de ES6 solo admiten herencia única, debe crear una cadena de clases que contenga todas las clases que desea mezclar. Entonces, digamos que desea crear una clase C que extienda tanto A como B, puede hacer esto:
El problema con esto es que es muy estático. Si luego decide que desea crear una clase D que se extienda B pero no A, tiene un problema.
Pero con algunos trucos inteligentes que usan el hecho de que las clases pueden ser expresiones, puede resolver esto creando A y B no directamente como clases, sino como fábricas de clases (usando brevemente las funciones de flecha):
Observe cómo solo decidimos en el último momento qué clases incluir en la jerarquía.
fuente
Esto no es realmente posible con la forma en que funciona la herencia prototípica. Veamos cómo funcionan los accesorios heredados en js
veamos qué sucede cuando accedes a un accesorio que no existe:
Puede usar mixins para obtener parte de esa funcionalidad, pero no obtendrá un enlace tardío:
vs
fuente
Se me ocurrió esta solución:
uso:
Mientras hagas estos trucos con tus clases escritas a medida, puedes encadenarlas. pero tan pronto como quiera extender alguna función / clase escrita de esa manera, no tendrá oportunidad de continuar el ciclo.
funciona para mí en el nodo v5.4.1 con el indicador --harmony
fuente
Desde la página es6-features.org/#ClassInheritanceFromExpressions , es posible escribir una función de agregación para permitir la herencia múltiple:
Pero eso ya se proporciona en bibliotecas como la agregación .
fuente
use Mixins para la herencia múltiple ES6.
fuente
one class inherits from 2 or more unrelated classes
? Lo que muestra su ejemplo es una clase que hereda de 2, pero clases relacionadas. Esta es una herencia única, no una herencia múltiple.classTwo
. Al carecer de un concepto de clase genuino, JS no tiene herencia estructural de todos modos. De improviso, no puedo concebir un escenario JS en el que los mixins se comporten de manera diferente de lo que cabría esperar conceptualizándolos como MI del verdadero mundo OO (aparte de la 'super' cadena definida); Tal vez alguna persona con más conocimientos que yo pueda suministrar uno.Bueno, Object.assign te da la posibilidad de hacer algo cercano, aunque un poco más como composición con clases de ES6.
No he visto esto usado en ningún lado, pero en realidad es bastante útil. Puede usar en
function shark(){}
lugar de class pero hay ventajas de usar class en su lugar.Creo que lo único diferente con la herencia con
extend
palabra clave es que la función no vive solo enprototype
el objeto sino también en él.Por lo tanto, ahora, cuando lo hace,
new Shark()
loshark
creado tiene unbite
método, mientras que solo su prototipo tiene uneat
métodofuente
No hay una manera fácil de hacer una herencia de clases múltiples. Sigo la combinación de asociación y herencia para lograr este tipo de comportamiento.
Espero que esto sea útil.
fuente
Esta solución ES6 funcionó para mí:
multiple-herencia.js
main.js
Rendimientos en la consola del navegador:
fuente
Pasé media semana tratando de resolver esto por mí mismo, y escribí un artículo completo sobre él, https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS , y espero que ayude a algunos de ustedes.
En resumen, así es como se puede implementar MI en JavaScript:
Y aquí está specialize_with () one-liner:
Nuevamente, mire https://github.com/latitov/OOP_MI_Ct_oPlus_in_JS .
fuente
en javascript no puede dar a una clase (función de constructor) 2 objetos prototipo diferentes y debido a que la herencia en javascript funciona con prototipo, entonces no puede usar más de 1 herencia para una clase, pero puede agregar y unir la propiedad del objeto Prototype y esa propiedad principal dentro de una clase manualmente con la refactorización de las clases principales y luego se extiende esa nueva versión y la clase unida a su clase de destino tiene código para su pregunta:
fuente
Mi respuesta parece menos código y funciona para mí:
fuente
use la extensión con una función personalizada para manejar la herencia múltiple con es6
fuente
También agregaré mi solución: me pareció la más amigable para mí por lo que leí en este hilo.
Puedes usarlo así así:
fuente
Como prueba de concepto, hice la siguiente función. Toma una lista de clases y las compone en una nueva clase (el último prototipo gana para que no haya conflictos). Al crear una función compuesta, el usuario puede elegir usar todos los constructores originales [ sic! ] o pasar el suyo. Este fue el mayor desafío de este experimento: llegar a una descripción de lo que el constructor debería hacer. Copiar métodos en un prototipo no es un problema, pero cuál es la lógica prevista del objeto recién compuesto. ¿O tal vez debería ser sin constructor? En Python, por lo que sé, encuentra el constructor coincidente, pero las funciones en JS son más aceptables, por lo tanto, uno puede pasar a una función casi todo y desde la firma no estará claro.
No creo que esté optimizado, pero el propósito era explorar posibilidades.
instanceof
no se comportará como se esperaba, lo que, supongo, es un fastidio, ya que a los desarrolladores orientados a la clase les gusta usar esto como herramienta.Quizás JavaScript simplemente no lo tenga.
Publicado originalmente aquí (gist.github.com).
fuente
https://www.npmjs.com/package/ts-mixer
¡Con el mejor soporte de TS y muchas otras funciones útiles!
fuente
Aquí hay una manera increíble / realmente horrible de extender múltiples clases. Estoy utilizando un par de funciones que Babel puso en mi código transpilado. La función crea una nueva clase que hereda class1, y class1 hereda class2, y así sucesivamente. Tiene sus problemas, pero es una idea divertida.
fuente