Herança Múltipla com JavaScript


Minha primeira linguagem de programação foi o Python, e uma coisa que sempre gostei foi o esquema da herança múltipla. Pois, e isso é minha opinião, acredito que ajuda a desenvolver melhor e mais rápido

Após muita pesquisa, notei que o JavaScript/ES6 faz muita coisa, exceto a falta de suporte de herança múltipla para classes. Ter que encadear classes únicas para fazer herança múltipla é bem complicado.

Após pesquisar bastante, encontrei em um site em inglês (CodeProject: JavaScript ES6 Multiple Inheritance Class) o código abaixo. Com isso estou traduzindo o que posso e disponibilizando em português. Espero que ajude a outros

class multi {
    // metodo Inherit, para criar classes base/mãe
    static inherit(..._bases) {
        class classes {

            // A classe base
            get base() { return _bases; }

            constructor(..._args) {
                var index = 0;

                for (let b of this.base) {
                    let obj = new b(_args[index++]);
                    multi.copy(this, obj);
                }
            }

        }

        // Copia as propriedades e metodos
        for (let base of _bases) {
            multi.copy(classes, base);
            multi.copy(classes.prototype, base.prototype);
        }

        return classes;
    }

    // Copia as propriedades de uma classe para outra
    static copy(_target, _source) {
        for (let key of Reflect.ownKeys(_source)) {
            if (key !== "constructor" && key !== "prototype" && key !== "name") {
                let desc = Object.getOwnPropertyDescriptor(_source, key);
                Object.defineProperty(_target, key, desc);
            }
        }
    }
}

Como funciona?

Para que a herança múltipla funcione, utilizei muitos dos novos recursos do ES6 em combinação com o ES5. Em vez de passar uma classe para a extensão, passamos uma função estática chamada inherit, que retorna uma classe depois de mesclar propriedades e métodos juntos de outras classes nomeadas. Dentro do método inherit, recebemos um parâmetro REST com todos os nomes de classes para herdar.

// Herança Simples
class person extends ages

// Herança Multipla
class person extends multi.inherit(ages, genders)

get base() { return _bases; }

Esse é um recurso importante para criar as instâncias de cada classe e copiar suas propriedades no método do construtor. Nós encaminhamos os parâmetros do super () para o construtor.

constructor(..._args)
{
  var index = 0;

  for (let b of this.base) 
  {
    let obj = new b(_args[index++]);
    multi.copy(this, obj);
  }
}

Abaixo está um exemplo completo de trabalho de herança múltipla junto com um exemplo

// Classe para criar herança multipla
class multi {
    // metodo Inherit, para criar classes base/mãe
    static inherit(..._bases) {
        class classes {

            // A classe base
            get base() { return _bases; }

            constructor(..._args) {
                var index = 0;

                for (let b of this.base) {
                    let obj = new b(_args[index++]);
                    multi.copy(this, obj);
                }
            }

        }

        // Copia as propriedades e metodos
        for (let base of _bases) {
            multi.copy(classes, base);
            multi.copy(classes.prototype, base.prototype);
        }

        return classes;
    }

    // Copia as propriedades de uma classe para outra
    static copy(_target, _source) {
        for (let key of Reflect.ownKeys(_source)) {
            if (key !== "constructor" && key !== "prototype" && key !== "name") {
                let desc = Object.getOwnPropertyDescriptor(_source, key);
                Object.defineProperty(_target, key, desc);
            }
        }
    }
}

class idades {
    constructor(_idade) { this.idade = _idade; }
    set idade(_i) { this._idade = _i; }
    get idade() { return this._idade; }
    increase() { this.idade++; }
}

class sexos {
    constructor(_sexo) { this.sexo = _sexo; }
    set sexo(_s) { this._sexo = _s; }
    get sexo() { return this._sexo; }
    male() { this._sexo = 'M'; }
    female() { this._sexo = 'F'; }
}

class pessoa extends multi.inherit(idades, sexos)
{
    constructor(...args) {
        super(18, 'M');
        this.nome = args[0];
    }

    set nome(_n) { this.nome = _n; }
    get nome() { return this._nome; }
}

var p = new pessoa('Pericles');
console.log(p.nome, p.idade, p.sexo);

 

Deixe um comentário