面试题答案
一键面试问题分析
- 参数类型协变:在运行时,如果子类方法放宽了参数类型,可能会导致传入不符合基类预期的数据,从而引发运行时错误。例如,基类方法期望接收一个
string
类型参数,子类放宽为any
类型,调用者可能传入一个非string
类型数据,在子类方法中按string
相关逻辑处理时就会出错。 - 返回类型逆变:虽然在类型系统中允许返回类型收紧,但如果在运行时调用者按照基类返回类型的预期使用返回值,而子类返回的实际类型过于特殊,可能导致调用者使用时出现类型不匹配问题。例如,基类返回
number
类型,子类返回1
这个字面量类型,调用者可能会对返回值进行数学运算,但如果返回值是1
这个字面量类型,某些运算可能不被支持(比如++
操作在严格模式下对字面量1
可能会有问题)。
代码示例
// 基类
class Base {
process(data: string): number {
return data.length;
}
}
// 子类重写方法,参数类型协变
class Child1 extends Base {
process(data: any): number {
if (typeof data ==='string') {
return data.length;
}
return 0;
}
}
// 子类重写方法,返回类型逆变
class Child2 extends Base {
process(data: string): 1 {
return 1;
}
}
// 使用示例
function useBase(base: Base) {
const result = base.process('test');
console.log(result);
}
const child1 = new Child1();
const child2 = new Child2();
useBase(child1);
useBase(child2);
在上述代码中,Child1
类重写 process
方法时放宽了参数类型,通过在方法内部进行类型检查来保证运行时不会因为参数类型问题出错。Child2
类重写 process
方法时收紧了返回类型,虽然类型系统允许,但调用者在使用返回值时要注意其实际类型。在 useBase
函数中统一使用基类来调用 process
方法,展示了如何在保证类型安全的同时处理这种情况。