在继承抽象 class 的 class 实例上调用方法

Calling a method on an instance of a class that inherits an abstract class

我这里有这个摘要class:

export abstract class BaseStepComponent {
    /** base-step ctor */
    constructor() {

    }

    abstract getValue(): string;

}

还有一个组件继承了它:

export class SingleChoiceStepComponent extends BaseStepComponent {
    /** single-choice-step ctor */
    constructor() {
        super();
    }
    
    @ViewChild("itemList") itemList: ElementRef;

    getValue(): string {
        return this.itemList.nativeElement.value;
    }

}

我有一些这样的组件,它们在 getValue()

中有不同的逻辑

在我的应用程序的其他地方,我在组件中有这个成员:

stepItems: QueryList<any>;
@ViewChildren("stepItem") set stepItemsContent(content: QueryList<any>) {
    let items = content.toArray();
    if (items.length > 0) {
        this.stepItems = content;
    }
}

“步骤”是向导(多页表单)中的字段,应用程序并不真正知道呈现的“步骤”的类型以及它们的数量(可由管理员配置 UI ), 但他们都继承了 BaseStepComponent

后面想收集getValue()返回的值,但是遇到下面评论中提到的问题

let values: any[] = [];
this.stepItems.forEach(step => {
 let v = step.getValue(); //works in IDE, not at runtime, sadly.
  values.push({ key: step.key, value: v });
});

由于 BaseStepComponent 是抽象的,我不能做类似的事情:

let instance = new BaseStepComponent();
instance = Object.assign(instance, step);

所以我有点卡住了。知道如何实现吗?

您可以使用类似下面的内容,

export abstract class BaseStepComponent {
/** base-step ctor */
constructor() {}

abstract getValue(): string;
}

@Component({
 selector: "step1",
 template: `
 <h1>Step 1</h1>
 `,
 providers: [{ provide: BaseStepComponent, useExisting: Step1Component }]
})
export class Step1Component extends BaseStepComponent {
 @Input() name: string;

 getValue(): string {
  return "Step1Component";
 }
}

@Component({
 selector: "step2",
 template: `
 <h1>Step 2</h1>
 `,
 providers: [{ provide: BaseStepComponent, useExisting: Step2Component }]
})
export class Step2Component extends BaseStepComponent {
 @Input() name: string;

 getValue(): string {
  return "Step2Component";
 }
}

并使用它,

export class AppComponent {
  name = "Angular " + VERSION.major;

  @ViewChildren(BaseStepComponent) items: QueryList<BaseStepComponent>;

  ngAfterViewInit() {
    this.items.map((step: BaseStepComponent) => {
      console.log(step.getValue());
    });
  }
}

这里是 stackblitz.