Virguerías en JavaScript I - Herencia y Mixins

Hace pocos días, vi durante una jornada normal de trabajo un código que me llamó muchísimo la atención, siendo un neófito del JavaScript moderno como me considero. El código del que hablo tenía un aspecto similar a esto:

function tagged(BaseClass) {  
    return class extends BaseClass {
        ...
    }
}

Si leemos tal cual es bastante entendible: Una función que devuelve una clase anónima que extiende de otra clase pasada como parámetro.

Aquí empezaron las cosas raras para mi; porque aunque ya se ha dicho, esta función devuelve una clase, no una instancia de una clase por lo que tenemos en realidad es una factoría de clases. Esto implica que podemos instanciar el resultado de la función tagged.

Esto se conoce como Mixins, y representan una forma un tanto extraña de herencia para alguien que aprendió directamente POO con Java como es un servidor. Si alguien quiere saber más sobre los mixins y sus ventajas os recomiendo este post ya que traducir su contenido alargaría este post innecesariamente y no aportaría gran cosa.

Un ejemplo de uso de mixins podría ser el siguiente:

class Person {  
    _name;
    _age;

    constructor(name, age) {
        this._name = name;
        this._age = age;
    }
}

function Tagged(BaseType) {  
    return class extends BaseType {
        _tag;

        constructor(name, age, tag) {
            super(name, age);
            this._tag = tag;
        }
    }
}

const TaggedPerson = Tagged(Person);

const p = new Person('Oscar', 12);

const t = new TaggedPerson('Pedro', 14, 1);

console.log(p._tag);  
console.log(t._tag);  

La salida de este pequeño ejemplo sería

undefined  
1  

ya que mediante el uso de mixins hemos creado una subclase de Person que tiene una propiedad _tag que no existe en la propia clase Person. Una cosa interesante de los mixins es que pueden heredar de otros mixins, haciéndolos encadenables, pudiendo extender el ejemplo anterior de la siguiente manera, aprovechando que todas las clases creadas por el método Tagged cuentan con un miembro _tag;

function LogTag(BaseType) {  
    return class extends BaseType {
        logTag() {
            console.log(this._tag);
        }
    }
}

...

const LoggedPerson = LogTag(Tagged(Person));  
const a = new LoggedPerson('Ana', 16, 3);  
a.logTag();  

La salida del programa pasaría a ser

undefined  
1  
3  

Gracias al uso de mixins se puede crear una jerarquía muy rica y dinámica de una manera realmente simple y quitando de enmedio el tener que escribrir clases enteras para extender otras clases.

Gabriel Ferreiro

Read more posts by this author.

Subscribe to Gabriel Ferreiro

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!