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.