TypeScript 中的多重繼承

Migel Hewage Nimesha 2024年2月15日
  1. TypeScript 中的單一繼承
  2. TypeScript 類的多重繼承
  3. TypeScript 介面的多重繼承
  4. TypeScript Mixins 的多重繼承
TypeScript 中的多重繼承

多年來已經發展了幾種程式設計正規化。物件導向程式設計(OOP)是基於現實世界實體及其互動的主要正規化之一。

繼承是眾所周知的 OOP 概念之一,它允許子實體獲取父實體的屬性和行為。

TypeScript 中的單一繼承

TypeScript 在某種程度上支援 OOP 技術。它支援從一個父實體繼承,允許程式設計師有效地重用他們的程式碼。

我們可以使用 extends 關鍵字從父實體繼承,如下所示。

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

class Cat extends Animal {

    constructor() {
        super();
    }
}

const cat = new Cat();

輸出:

"Animal class"

這稱為單繼承,給定的類只能擴充套件到一個父類。

TypeScript 類的多重繼承

在類 Java 語言中,可以從多個父實體獲取屬性和行為。這稱為多重繼承。

TypeScript 不支援多重繼承。

多重繼承

讓我們嘗試使用 extends 在 TypeScript 中擴充套件多個父類。

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

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

class Employee extends Engineer, Person {
}

然後,讓我們轉譯 TypeScript 程式碼,如下所示。

tsc example1.ts

輸出:

TypeScript 多重繼承 - 輸出 1

正如預期的那樣,它給出了一個錯誤,即 TypeScript 只允許擴充套件單個類。

TypeScript 介面的多重繼承

TypeScript 介面支援開箱即用的多重繼承。它們可以擴充套件多個類。

讓我們建立兩個類,PersonEngineer,並新增一些虛擬方法。

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;
}

由於 Employee 類不能擴充套件多個父類,我們應該使用同名 Employee 的介面來使用 TypeScript 宣告合併。通過這種方式,你可以合併介面和類。

讓我們建立 Employee 介面,它擴充套件了 PersonEngineer 類,如下所示。

interface Employee extends Person, Engineer {
}

讓我們轉譯 TypeScript 程式碼並檢查是否有任何錯誤。

輸出:

TypeScript 多重繼承 - 輸出 2

正如預期的那樣,在介面宣告中使用具有多個父類的 extends 時沒有錯誤。因此,介面支援多重繼承。

但是如果我們在繼承類內部呼叫一個方法,還是有問題的。我們無權訪問方法實現。

讓我們嘗試呼叫 sayImAnEngineer() 方法。

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

我們應該先編譯程式碼;它不會給出任何錯誤。然後,嘗試執行生成的 JavaScript;它會引發錯誤,如以下輸出所示。

輸出:

TypeScript 多重繼承 - 輸出 3

TypeScript 找不到 sayImAnEngineer 方法。我們可以通過使用 TypeScript mixins 來克服這個問題。

TypeScript Mixins 的多重繼承

TypeScript mixins 機制可以將父類中所有可用的方法複製到派生類或子類中。mixin 建立方法應該遍歷父類中的所有屬性並檢索內容。

然後,它應該按原樣設定派生類中的所有內容。TypeScript 官方文件提供了一個方法:【mixin 建立方法】。

建議在你的 TypeScript 檔案中使用,如下所示。

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)
      );
    });
  });
}

讓我們在 TypeScript 示例中包含 applyMixins 方法。

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)
      );
    });
  });
}

現在,讓我們呼叫 applyMixins 方法,如下所示。

applyMixins(Employee, [Person, Engineer]);

第一個引數應該是派生類;在這種情況下,它是 Employee 類。下一個引數是一個陣列,其中包含派生類將擴充套件的所有父類。

最後,讓我們建立一個 Employee 物件並從 Engineer 父類呼叫 sayImAnEngineer 方法。

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

輸出:

TypeScript 多重繼承 - 輸出 4

這次沒有錯誤;這意味著 mixins 技術有效。這樣,你可以在 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.