如何让抽象类中的函数返回typescript中子类的实例
有没有可能有这样的伪代码:如何让抽象类中的函数返回typescript中子类的实例,typescript,inheritance,abstract-class,parent-child,extends,Typescript,Inheritance,Abstract Class,Parent Child,Extends,有没有可能有这样的伪代码: abstract class AbstractParent { protected value: number; constructor(value: number) { this.value = value; } ... public times(multiplicator: number) { return new ???(value * multiplicator); } } 它为
abstract class AbstractParent {
protected value: number;
constructor(value: number) {
this.value = value;
}
...
public times(multiplicator: number) {
return new ???(value * multiplicator);
}
}
它为
类Foo扩展AbstractParent
返回一个新的Foo
,为类Bar扩展AbstractParent
返回一个新的Bar
?一种可维护的方法是将时间
计算保留在基类中,并在Foo
和Bar
内部执行单独的create
工厂方法。这样,基类就不知道它的扩展子类
在AbstractParent
中声明create
为abstract
,以确保它将在所有子类中实现。返回类型确保对于调用times
,返回的实例具有相同的子类类型()
您可以将子类型传递到父构造函数并保存引用。这就避免了父母必须知道所有可能的孩子类型(尽管我同意另一个答案,即可能有更好的方法来实现你的总体目标)。类似这样的内容():
type ChildConstructor=new(值:number,ChildConstructor:ChildConstructor)=>Child;
抽象类AbstractParent{
保护值:数字;
受保护的childConstructor:childConstructor;
构造函数(值:number,子构造函数:子构造函数){
这个值=值;
this.childConstructor=childConstructor;
}
公共时间(乘法器:数字):Child{
返回新的this.childConstructor(this.value*乘法器,this.childConstructor);
}
}
类Foo扩展了抽象父类{
构造函数(值:number){
超级(价值,Foo);
}
}
类栏扩展了抽象父类{
构造函数(值:number){
超级(值,巴);
}
}
请注意,要获得100%的类型安全性,每个子类需要至少有一个额外的私有属性或方法,以避免TypeScript的“duck typing”将类视为可互换的(因为它们共享相同的属性和方法)。我同意在这里使用是一个不错的选择。但是,我不理解您的实现选择。。。方法
times
应调用工厂方法。应保护工厂方法。工厂方法的实现应该只实例化相应的类(不调用方法次数)。你是对的,把它和之前的备选方法混在一起了<在OP的问题中,code>times是公共的,因此有一个公共基times
方法更有意义,它在内部调用多态保护工厂方法。更新答案,谢谢!谢谢我尝试了这种方法,现在我得到了TypeError:this.create在我尝试执行const foo=new foo(42)时不是一个函数。times(2)
@Hade0011TypeError
是一个JavaScript运行时错误,与TS无关。在答案中,playerd是有效的,因此您可以提供一个示例吗?听起来更像是你在某处混淆了这个上下文…@ford04你完全正确。我修复了我的这个
,现在它就像一个魔咒一样工作。非常感谢!
abstract class AbstractParent {
protected value: number;
constructor(value: number) {
this.value = value;
}
times(multiplicator: number) {
return this.create(this.value * multiplicator);
}
// factory method creates instances of same polymorphic type (Foo / Bar)
protected abstract create(value: number): this
}
class Foo extends AbstractParent {
create(value: number) {
// Polymorphic this type is Foo here, so it's OK to return a Foo.
// Compiler is not aware of the class context, so we cast.
return new Foo(value) as this
}
}
class Bar extends AbstractParent {
// same as Foo
create(value: number) {
return new Bar(value) as this
}
}
const foo = new Foo(42).times(2) // Foo
const bar = new Bar(42).times(3) // Bar
type ChildConstructor<Child> = new (value: number, childConstructor: ChildConstructor<Child>) => Child;
abstract class AbstractParent<Child extends AbstractParent<Child>> {
protected value: number;
protected childConstructor: ChildConstructor<Child>;
constructor(value: number, childConstructor: ChildConstructor<Child>) {
this.value = value;
this.childConstructor = childConstructor;
}
public times(multiplicator: number): Child {
return new this.childConstructor(this.value * multiplicator, this.childConstructor);
}
}
class Foo extends AbstractParent<Foo> {
constructor(value: number) {
super(value, Foo);
}
}
class Bar extends AbstractParent<Bar> {
constructor(value: number) {
super(value, Bar);
}
}