简体   繁体   English

Typescript - 将类类型存储为变量,以便从中创建对象或其他等效功能

[英]Typescript - Store Class Type As Variable In Order to Create Objects From It Or Other Equivalent Functionality

Preface - I have looked at similar posts to this one on SO, but the answers did not seem applicable.前言 - 我在 SO 上看过与此类似的帖子,但答案似乎并不适用。

I have an abstract class with the following method (simplified):我有一个具有以下方法(简化)的抽象类:

playAnimation() {
    let animator =  this.createAnimator(this.animatorData)  
    await animator.animate()
}

Create animator has the following definition inside that abstract class: Create animator 在该抽象类中具有以下定义:

abstract createAnimator(animatorData: Object): Animator

A subclass might implement createAnimator like this:一个子类可能会像这样实现createAnimator

createAnimator(animatorData: StandardAnimatorData) {
    return new RiverAnimator(animatorData.addMessage, animatorData.assetsDir) 
}

or like this:或者像这样:

createAnimator(animatorData: StandardAnimatorData) {
    return new BridgeAnimator(animatorData.addMessage, animatorData.assetsDir) 
}

As you can see - both of the sub classes's implementations of createAnimator are roughly identical, except for the type of the Animator being returned.如您所见 - createAnimator两个子类的实现大致相同,除了返回的Animator的类型。

Sidenote BridgeAnimator and RiverAnimator both implement the Animator interface, but if the solution requires Animator to be an abstract class, I can change it. BridgeAnimatorRiverAnimator都实现了Animator接口,但是如果解决方案要求Animator是抽象类,我可以更改它。

Is there a way to move createAnimator into the abstract base class?有没有办法将createAnimator移动到抽象基类中?

Ideally the abstract class would have an abstract variable that is the type of the class that createAnimator should return.理想情况下,抽象类应该有一个抽象变量,它是createAnimator应该返回的类的类型。 Subclasses would merely implement that variable.子类只会实现该变量。 Then createAnimator would use that variable to return the proper type of Animator .然后createAnimator将使用该变量返回正确类型的Animator

Yes, you can do something like this (I made one big code snippet so I can verify that everything compiles):是的,你可以做这样的事情(我做了一个大的代码片段,所以我可以验证一切都编译):

interface Animator {
  animate(): Promise<void>;
}

class RiverAnimator implements Animator {
  async animate() { }
  constructor(addMessage: unknown, assetsDir: unknown) { }
}
class BridgeAnimator implements Animator {
  async animate() { }
  constructor(addMessage: unknown, assetsDir: unknown) { }
}

interface StandardAnimatorData {
  addMessage: unknown;
  assetsDir: unknown;
}

// Common interface for the constructor functions RiverAnimator and BridgeAnimator 
interface AnimatorConstructor {
  new(addMessage: unknown, assetsDir: unknown): Animator;
}

abstract class AbstractOuterClass {
  abstract animatorConstructor: AnimatorConstructor;
  animatorData: StandardAnimatorData;
  createAnimator(data: StandardAnimatorData) {
    return new this.animatorConstructor(data.addMessage, data.assetsDir);
  } 
  async playAnimation() {
    let animator = this.createAnimator(this.animatorData);
    await animator.animate();
  }
}

class SubOuterClass1 extends AbstractOuterClass {
  animatorConstructor = RiverAnimator;
}

class SubOuterClass2 extends AbstractOuterClass {
  animatorConstructor = BridgeAnimator;
}

But it's not clear to me that this is any better than implementing createAnimator in SubOuterClass1 and SubOuterClass2 .但我不清楚这是否比在SubOuterClass1SubOuterClass2实现createAnimator更好。

Another approach is to use the power of generics:另一种方法是使用泛型的力量:

declaration:宣言:

createAnimator<T extends Animator>(
    type: { new(addMessage: unknown, assetDir: unknown): T }, 
    animatorData: StandardAnimatorData
): T {
    return new type(animatorData.addMessage, animatorData.assetDir);
}

invocation:调用:

let animator = this.createAnimator(BridgeAnimator, animatorData);
await animator.animate();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM