子类不能使用子类型属性代替父类属性



好吧,奇怪的标题,不知道该怎么说。 所以这就是问题所在。 我的印象是,如果我将父构造函数属性的子类型传递给子构造函数属性,一切都会起作用。然而,事实并非如此。如果我尝试在子属性上使用子类型方法,则会出现错误。

interface IDataMaper{
save():void
}
interface IReactiveDataMapper extends IDataMaper{
saveReactive():void
}

class A {
constructor(protected mapper: IDataMaper) {}
}
class B extends A {
constructor(mapper: IReactiveDataMapper) {
super(mapper)//no errror here
// this.mapper.saveReactive() //error
}
}   

打字稿游乐场

问题是您正在从this上下文访问mapper实例。请注意类 A 的构造函数中的protected mapper: IDataMapper。通过将关键字protected添加到前面,可以强制类 A 将具有一个名为mapper的受保护成员,其类型为IDataMapper。在 B 的构造函数中,您没有关键字protected,这意味着 B 的this-context 的受保护成员mapper不会被覆盖,并且使用 A 存储的IDataMapper属性。将protected-前缀添加到 B 构造函数中的变量,使其覆盖成员,您将不会遇到错误。

interface IDataMaper{
save():void
}
interface IReactiveDataMapper extends IDataMaper{
saveReactive():void
}

class A {
constructor(protected mapper: IDataMaper) {}
}
class B extends A {
constructor(protected mapper: IReactiveDataMapper) {
super(mapper);
this.mapper.saveReactive();
}
}   

游乐场链接

Lukas的回答很好地解释了为什么会发生这个错误;this.mapper的类型是IDataMapper,而不是更具体的IReactiveDataMapper类型。

作为不需要更改字段类型或使用不同类型的新字段声明的替代解决方案,您可以在参数mapper上调用该方法,该方法引用与this.mapper相同的对象,但具有更具体的类型:

class B extends A {
constructor(mapper: IReactiveDataMapper) {
super(mapper);
mapper.saveReactive(); // instead of this.mapper
}
}

如果只需要构造函数中更具体的类型,则此选项可能更简单,如示例中所示。如果你需要this.mapper在子类中的其他方法中拥有更具体的类型,那么 Lukas 的答案是最好的方法。

最新更新