Herencia múltiple en TypeScript

Migel Hewage Nimesha 30 enero 2023
  1. Herencia única en TypeScript
  2. Herencia múltiple con clases de TypeScript
  3. Herencia múltiple con interfaces TypeScript
  4. Herencia múltiple con mezclas de TypeScript
Herencia múltiple en TypeScript

Hay varios paradigmas de programación que han evolucionado a lo largo de los años. La Programación Orientada a Objetos (POO) es uno de los principales paradigmas basados ​​en entidades del mundo real y su interacción.

La herencia es uno de los conceptos OOP bien conocidos que permite adquirir las propiedades y comportamientos de la entidad matriz por subentidades.

Herencia única en TypeScript

TypeScript admite técnicas de programación orientada a objetos hasta cierto punto. Admite la herencia de una entidad principal, lo que permite a los programadores reutilizar su código de manera efectiva.

Podemos heredar de una entidad padre usando la palabra clave extiende, como se muestra a continuación.

class Animal {
    constructor() {
        console.log("Animal class");
    }
}

class Cat extends Animal {

    constructor() {
        super();
    }
}

const cat = new Cat();

Producción :

"Animal class"

Esto se denomina herencia única, que la clase dada puede extenderse a una sola clase principal.

Herencia múltiple con clases de TypeScript

Es posible adquirir propiedades y comportamientos de más de una entidad principal en lenguajes similares a Java. Esto se llama herencia múltiple.

TypeScript no admite la herencia múltiple.

Herencia múltiple

Intentemos extender varias clases principales en TypeScript usando extiende.

class Engineer {
    constructor() {
        console.log("Employee class");
    }
}

class Person {
    constructor() {
        console.log("Person class");
    }
}

class Employee extends Engineer, Person {
}

Luego, transpilemos el código TypeScript, como se muestra a continuación.

tsc example1.ts

Producción:

Herencia múltiple de TypeScript - Salida 1

Como era de esperar, da un error de que TypeScript solo permite extender una sola clase.

Herencia múltiple con interfaces TypeScript

Las interfaces de TypeScript admiten la herencia múltiple desde el primer momento. Pueden extender más de una clase.

Creemos dos clases, Persona e Engineer, y agreguemos algunos métodos ficticios.

class Person {
    name: string;

    constructor() {
       console.log("Person class");
    }

    sayImAPerson(){
        console.log("Hey, I am a person");
    }
}

class Engineer {
    salary: number;
    constructor() {
        console.log("Engineer class");
    }
    sayImAnEngineer(){
        console.log("I am an engineer too");
    }
}

A continuación, crearemos un nuevo tipo o clase para ampliar las dos clases anteriores.

class Employee {
    empId: string;
}

Dado que la clase Employee no puede extenderse a más de una clase principal, deberíamos usar una interfaz con el mismo nombre Employee para usar la combinación de declaraciones de TypeScript. De esta manera, puede fusionar interfaces y clases.

Vamos a crear la interfaz Employee, que extiende las clases Persona e Engineer, como se muestra a continuación.

interface Employee extends Person, Engineer {
}

Transpilemos el código de TypeScript y verifiquemos si obtenemos algún error.

Producción:

Herencia múltiple de TypeScript - Salida 2

Como era de esperar, no hay errores al usar extends con más de una clase principal dentro de la declaración de la interfaz. Por lo tanto, la interfaz admite herencias múltiples.

Pero todavía hay un problema si llamamos a un método dentro de la clase heredada. No tenemos acceso a las implementaciones del método.

Intentemos llamar al método sayImAnEngineer().

let emp: Employee = new Employee;
emp.sayImAnEngineer();

Primero deberíamos transpilar el código; no dará ningún error. Luego, intente ejecutar el JavaScript generado; generaría un error, como se muestra en el siguiente resultado.

Producción:

Herencia múltiple de TypeScript - Salida 3

TypeScript no pudo localizar el método sayImAnEngineer. Podemos superar esto usando mixins de TypeScript.

Herencia múltiple con mezclas de TypeScript

El mecanismo mixins de TypeScript puede copiar todos los métodos disponibles en las clases principales a la clase o subclase derivada. El método de creación de mixin debe pasar por todas las propiedades de las clases principales y recuperar el contenido.

Luego, debe establecer todo el contenido de la clase derivada tal como está. Hay un método proporcionado por la documentación oficial de TypeScript: método de creación de mixin.

Se recomienda utilizar dentro de su archivo TypeScript, como se muestra a continuación.

function applyMixins(derivedCtor: any, constructors: any[]) {
  constructors.forEach((baseCtor) => {
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
          Object.create(null)
      );
    });
  });
}

Incluyamos el método applyMixins dentro de nuestro ejemplo de TypeScript.

class Person {
    name: string;

    constructor() {
       console.log("Person class");
    }

    sayImAPerson(){
        console.log("Hey, I am a person");
    }
}

class Engineer {
    salary: number;
    constructor() {
        console.log("Engineer class");
    }
    sayImAnEngineer(){
        console.log("I am an engineer too");
    }
}

class Employee {
    empId: string;
}

interface Employee extends Person, Engineer {

}

function applyMixins(derivedCtor: any, constructors: any[]) {
  constructors.forEach((baseCtor) => {
    Object.getOwnPropertyNames(baseCtor.prototype).forEach((name) => {
      Object.defineProperty(
        derivedCtor.prototype,
        name,
        Object.getOwnPropertyDescriptor(baseCtor.prototype, name) ||
          Object.create(null)
      );
    });
  });
}

Ahora, llamemos al método applyMixins, como se muestra a continuación.

applyMixins(Employee, [Person, Engineer]);

El primer parámetro debe ser la clase derivada; en este caso, es la clase Employee. El siguiente parámetro es una matriz que contiene todas las clases principales que extendería la clase derivada.

Finalmente, creemos un objeto Employee y llamemos al método saySoyUnIngeniero de la clase principal Engineer.

let emp: Employee = new Employee;
emp.sayImAnEngineer();

Producción:

Herencia múltiple de TypeScript - Salida 4

No hay errores esta vez; significa que la técnica mixins funcionó. De esta forma, puede implementar las herencias múltiples en TypeScript.

Migel Hewage Nimesha avatar Migel Hewage Nimesha avatar

Nimesha is a Full-stack Software Engineer for more than five years, he loves technology, as technology has the power to solve our many problems within just a minute. He have been contributing to various projects over the last 5+ years and working with almost all the so-called 03 tiers(DB, M-Tier, and Client). Recently, he has started working with DevOps technologies such as Azure administration, Kubernetes, Terraform automation, and Bash scripting as well.