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 只允許擴充套件單個類。
TypeScript 介面的多重繼承
TypeScript 介面支援開箱即用的多重繼承。它們可以擴充套件多個類。
讓我們建立兩個類,Person
和 Engineer
,並新增一些虛擬方法。
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
介面,它擴充套件了 Person
和 Engineer
類,如下所示。
interface Employee extends Person, Engineer {
}
讓我們轉譯 TypeScript 程式碼並檢查是否有任何錯誤。
輸出:
正如預期的那樣,在介面宣告中使用具有多個父類的 extends
時沒有錯誤。因此,介面支援多重繼承。
但是如果我們在繼承類內部呼叫一個方法,還是有問題的。我們無權訪問方法實現。
讓我們嘗試呼叫 sayImAnEngineer()
方法。
let emp: Employee = new Employee;
emp.sayImAnEngineer();
我們應該先編譯程式碼;它不會給出任何錯誤。然後,嘗試執行生成的 JavaScript;它會引發錯誤,如以下輸出所示。
輸出:
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();
輸出:
這次沒有錯誤;這意味著 mixins 技術有效。這樣,你可以在 TypeScript 中實現多重繼承。
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.