TypeScript父类类型对象数组能否接收子类实例并保留子类行为
TypeScript 父类类型数组存储子类实例问题解答
结论
完全可以把Bar、Blah类的实例push到声明为Foo[]类型的fooArray数组中,push后的实例会完整保留各自子类的所有行为特性,不会有任何丢失。
具体说明
- 编译层面:TypeScript 采用结构化类型校验,子类继承父类后天然满足父类的类型约束,完全符合里氏替换原则,因此往
Foo[]数组里push子类实例的操作不会触发类型错误,是合法写法。 - 运行时层面:TypeScript 的类型标注只在编译阶段生效,不会修改任何运行时的对象结构。你push进数组的
Bar、Blah实例本身的原型链、自有属性、自定义方法都不会发生任何改变,不会因为被存到父类类型的数组里就丢失子类特性。
验证代码
你可以运行下面的代码验证实际效果:
class Foo { commonLog() { console.log('父类公共方法执行'); } } class Bar extends Foo { barLog() { console.log('Bar子类独有方法执行'); } } class Blah extends Foo { blahLog() { console.log('Blah子类独有方法执行'); } } const fooArray: Foo[] = []; // 推入子类实例,TS编译无报错 fooArray.push(new Bar(), new Blah()); fooArray.forEach(item => { // 可直接调用父类定义的公共方法 item.commonLog(); // 通过类型收窄调用子类独有方法 if (item instanceof Bar) { item.barLog(); } if (item instanceof Blah) { item.blahLog(); } });
运行后你会看到所有父类、子类的方法都能正常执行,输出对应日志。
小提示
因为数组的声明类型是Foo[],TS静态检查时默认只知道数组元素符合Foo的结构,如果你不做类型收窄直接调用子类独有的方法,会报编译错误。但这只是静态检查的提示,不是运行时的问题,只要通过instanceof判断、自定义类型谓词等方式收窄类型,就可以正常访问子类的所有属性和方法。
内容的提问来源于stack exchange,提问作者hipsterstomper69
相关产品推荐
相关产品推荐

