Typescript - 将 Class 类型存储为变量,以便从中创建对象或其他等效功能
Typescript - Store Class Type As Variable In Order to Create Objects From It Or Other Equivalent Functionality
前言 - 我在 SO 上看过与此类似的帖子,但答案似乎不适用。
我有一个摘要class,方法如下(简化):
playAnimation() {
let animator = this.createAnimator(this.animatorData)
await animator.animate()
}
Create animator 在该摘要中有以下定义 class:
abstract createAnimator(animatorData: Object): Animator
子class 可能会像这样实现 createAnimator
:
createAnimator(animatorData: StandardAnimatorData) {
return new RiverAnimator(animatorData.addMessage, animatorData.assetsDir)
}
或者像这样:
createAnimator(animatorData: StandardAnimatorData) {
return new BridgeAnimator(animatorData.addMessage, animatorData.assetsDir)
}
如您所见 - classes 的两个子 createAnimator
实现大致相同,除了 Animator
的类型是 returned。
旁注 BridgeAnimator
和 RiverAnimator
都实现了 Animator
接口,但是如果解决方案要求 Animator
是抽象的 class,我可以更改它。
有没有办法将createAnimator
移动到抽象基础class中?
理想情况下,抽象 class 应该有一个抽象变量,它是 createAnimator
应该 return 的 class 的类型。 Subclasses 只会实现该变量。然后 createAnimator
将使用该变量 return Animator
.
的正确类型
是的,你可以这样做(我制作了一个大代码片段,以便我可以验证所有内容是否编译):
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;
}
但我不清楚这是否比在 SubOuterClass1
和 SubOuterClass2
中实施 createAnimator
更好。
另一种方法是利用泛型的力量:
声明:
createAnimator<T extends Animator>(
type: { new(addMessage: unknown, assetDir: unknown): T },
animatorData: StandardAnimatorData
): T {
return new type(animatorData.addMessage, animatorData.assetDir);
}
调用:
let animator = this.createAnimator(BridgeAnimator, animatorData);
await animator.animate();
前言 - 我在 SO 上看过与此类似的帖子,但答案似乎不适用。
我有一个摘要class,方法如下(简化):
playAnimation() {
let animator = this.createAnimator(this.animatorData)
await animator.animate()
}
Create animator 在该摘要中有以下定义 class:
abstract createAnimator(animatorData: Object): Animator
子class 可能会像这样实现 createAnimator
:
createAnimator(animatorData: StandardAnimatorData) {
return new RiverAnimator(animatorData.addMessage, animatorData.assetsDir)
}
或者像这样:
createAnimator(animatorData: StandardAnimatorData) {
return new BridgeAnimator(animatorData.addMessage, animatorData.assetsDir)
}
如您所见 - classes 的两个子 createAnimator
实现大致相同,除了 Animator
的类型是 returned。
旁注 BridgeAnimator
和 RiverAnimator
都实现了 Animator
接口,但是如果解决方案要求 Animator
是抽象的 class,我可以更改它。
有没有办法将createAnimator
移动到抽象基础class中?
理想情况下,抽象 class 应该有一个抽象变量,它是 createAnimator
应该 return 的 class 的类型。 Subclasses 只会实现该变量。然后 createAnimator
将使用该变量 return Animator
.
是的,你可以这样做(我制作了一个大代码片段,以便我可以验证所有内容是否编译):
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;
}
但我不清楚这是否比在 SubOuterClass1
和 SubOuterClass2
中实施 createAnimator
更好。
另一种方法是利用泛型的力量:
声明:
createAnimator<T extends Animator>(
type: { new(addMessage: unknown, assetDir: unknown): T },
animatorData: StandardAnimatorData
): T {
return new type(animatorData.addMessage, animatorData.assetDir);
}
调用:
let animator = this.createAnimator(BridgeAnimator, animatorData);
await animator.animate();