多继承的毛病
- TypeScript 不支持多重继承,这意味着一个类只能继承自一个类,因为他会潜在地增加程序的复杂性。
- 倘若,在支持多继承的环境下,一个子类所继承的两个父类都拥有一个同名的方法,子类在调用父类方法的时候,哪一个父类的方法被调用是不清楚或者说是有歧义的。
// 以下代码为错误代码
class Bat extends WingeAnimal, Mammal {
// ...
}
混入介绍
- 但是,有时候,我们会认为声明一个同时继承两个或多个类的类是一个好的想法。
- 为了避免多继承实现中潜在的危险,我们可以使用混入(又称混合,Mixin)特性。
- 首先是两个基类
class Mammal {
breathe() : string {
return "I'm alive!";
}
}
class WingedAnimal {
fly() : string {
return "I can fly!";
}
}
- 下面是子类,使用
implements替代extends,因此继承自的类仍需要实现,这里只是占坑
class Bat implements Mammal, WingedAnimal {
breathe: () => string;
fly: () => string;
}
使用以下函数,将基类的方法实现/复制到子类中
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
// 即是将“父类”原型对象中的属性,复制到子类的原型对象中
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
});
});
}
// 实现子类函数
applyMixins(bat, [Mammal, WingedAnimal]);
混入的限制
- 只能在继承树上继承一级的方法和属性。因为编译过后,在 JavaScript 中,父类的方法是在父类的原型对象中,子类的原型对象上找不到父类的方法。
- 如果两个或更多的父类包含了同名的方法,那么只会继承传入
applyMixins函数中baseCtor数组中最后一个类中的该方法。