Justin Fagnani descreve uma maneira muito clara (imho) de compor várias classes em uma usando o fato de que no ES2015, as classes podem ser criadas com expressões de classe .
Expressões vs declarações
Basicamente, assim como você pode criar uma função com uma expressão:
function myFunction() {} // function declaration
var myFunction = function(){} // function expression
você pode fazer o mesmo com as classes:
class MyClass {} // class declaration
var MyClass = class {} // class expression
A expressão é avaliada em tempo de execução, quando o código é executado, enquanto uma declaração é executada previamente.
Usando expressões de classe para criar mixins
Você pode usar isso para criar uma função que cria dinamicamente uma classe somente quando a função é chamada:
function createClassExtending(superclass) {
return class AwesomeClass extends superclass {
// you class body here as usual
}
}
O legal é que você pode definir toda a classe de antemão e apenas decidir em qual classe ela deve se estender quando você chamar a função:
class A {}
class B {}
var ExtendingA = createClassExtending(A)
var ExtendingB = createClassExtending(B)
Se você deseja misturar várias classes, porque as classes ES6 suportam apenas herança única, é necessário criar uma cadeia de classes que contenha todas as classes que você deseja misturar. Então, digamos que você queira criar uma classe C que estenda A e B, você pode fazer isso:
class A {}
class B extends A {}
class C extends B {} // C extends both A and B
O problema disso é que é muito estático. Se você decidir mais tarde criar uma classe D que estenda B, mas não A, você terá um problema.
Mas com alguns truques inteligentes usando o fato de que as classes podem ser expressões, você pode resolver isso criando A e B não diretamente como classes, mas como fábricas de classes (usando funções de seta por questões de brevidade):
class Base {} // some base class to keep the arrow functions simple
var A = (superclass) => class A extends superclass
var B = (superclass) => class B extends superclass
var C = B(A(Base))
var D = B(Base)
Observe como decidimos apenas no último momento quais classes incluir na hierarquia.