如何让抽象类中的函数返回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)
@Hade0011
TypeError
是一个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);
    }
}