我有一个我想扩展的基类:
export class BaseClass<T extends SomeOtherClass> {
constructor(param: ParamType) {
}
doSomething(param1: Param1Type): BaseClass<T> {
// do something with param1;
return this;
}
}
我的课程:
export class MyClass<T extends SomeOtherClass> extends BaseClass<T> {
constructor(param: ParamType) {
super(param);
}
doSomething(param1: Param1Type, param2: Param2Type): MyClass<T> {
// super.doSomething(param1);
// do something with param2;
return this;
}
}
但是我收到了警告:
Property 'doSomething' in type 'MyClass<T>' is not assignable to the same property in base type 'BaseClass<T>'.
Type '(param1: Param1Type, param2: Param2Type) => MyClass<T>' is not assignable to type '(param1: Param1Type) => BaseClass<T>'.
是否无法在打字稿中扩展方法签名?如果我需要向重写方法添加参数,如何扩展BaseClass的功能,这是在es6语法中调用父方法的正确方法。我知道在es6之前我可以调用BaseClass.prototype.doSomething.call(this,param1)。
答案 0 :(得分:2)
其他人指出的问题是,如果需要param2
,它会破坏多态性:
// We should be able to do this assignment
let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>("");
baseRef.doSomething("") // param2 is not required by the base class so MyClass will not receive it even though it NEEDS it
一种解决方案是使第二个参数成为可选项,因此调用baseRef.doSomething("")
也适用于派生类型:
export class MyClass<T extends SomeOtherClass> extends BaseClass<T> {
constructor(param: string) {
super(param);
}
doSomething(param1: string, param2?: string): MyClass<T> {
super.doSomething(param1);
return this;
}
}
第二个解决方案,如果我们只想在类之间共享代码,那就是不通过继承let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>("");
来禁止赋值BaseClass
,而是继承一个排除doSomething
的类方法:
type PartialBaseClass = new <T> (param: string) => { [P in Exclude<keyof BaseClass<T>, 'doSomething'>] : BaseClass<T>[P] }
const PartialBaseClass:PartialBaseClass = BaseClass
export class MyClass<T extends SomeOtherClass> extends PartialBaseClass<T> {
constructor(param: string) {
super(param);
}
doSomething(param1: string, param2: string): MyClass<T> {
BaseClass.prototype.doSomething.call(this, param1);
return this;
}
}
// This is now invalid !
let baseRef: BaseClass<SomeOtherClass> = new MyClass<SomeOtherClass>("") ;
答案 1 :(得分:0)
这违反了OOP,因为它会破坏多态性。您通常可以使用它的示例可以是基类Filter和派生类FilterWithDelay。父类实现了一个名为setFilter的方法。在OOP中,您可能有一个Filters数组,其中包含Filter和FilterWithDelay的实例。您通常可能希望迭代数组并在每个对象上调用setFilter。为此,子方法应该实现与父方法相同的函数签名。否则代码将需要检查每个实例以查看其是否为Filter或FilterWithDelay以传递其他参数。
为了实现FilterWithDelay,您可以扩展父类并将延迟作为参数传递给构造函数而不是方法。这样setFilter就可以实现通用接口。
export class BaseClass<T extends SomeOtherClass> {
constructor(param: ParamType) {
}
doSomething(param1: Param1Type): BaseClass<T> {
// do something with param1;
return this;
}
}
export class MyClass<T extends SomeOtherClass> extends BaseClass<T> {
constructor(param: ParamType, param2: Param2Type) {
super(param);
this.param2 = param2;
}
doSomething(param1: Param1Type): MyClass<T> {
return super.doSomething(param1 + this.param2);
}
}