扩展与在TypeScript中实现纯抽象类

Mic*_*Liu 59 abstract-class extends implements typescript

假设我有一个纯抽象类(即没有任何实现的抽象类):

abstract class A {
    abstract m(): void;
}
Run Code Online (Sandbox Code Playgroud)

就像在C#和Java中一样,我可以扩展抽象类:

class B extends A {
    m(): void { }
}
Run Code Online (Sandbox Code Playgroud)

C#和Java不同,我也可以实现抽象类:

class C implements A {
    m(): void { }
}
Run Code Online (Sandbox Code Playgroud)

课程BC行为有何不同?为什么我会选择一个与另一个?

(目前,TypeScript 手册语言规范不包括抽象类.)

tos*_*skv 72

工具关键字将A类为一个接口,这意味着C具有实现A中所定义的所有方法,无论他们是否有实现或没有一个.在C中也没有调用超级方法.

extends的行为更像您对关键字的期望.您必须仅实现抽象方法,并且可以使用/生成超级调用.

我想在抽象方法的情况下,它没有什么区别.但是你很少有一个只有抽象方法的,如果你这样做,将它转换为一个接口要好得多.

您可以通过查看生成的代码轻松地看到这一点.我做了一个游乐场例子在这里.

  • 如果`A`是纯抽象类,也许唯一可观察的区别是`instanceof`关键字的行为?我同意接口可能比纯抽象类更可取.但是,在Angular 2中,只有后者可以用作DI提供者令牌. (8认同)
  • @toskv,感谢您描述'implements'关键字对接口AND类的适用性。例如,AngularJS 2.0使用它来实现其“ OnInit” CLASS(而不是“ interface”)。我环顾四周,您对此有参考吗?我在TS文档中看不到它。 (2认同)

Tao*_*Tao 11

我被带到这里是因为我一直在问自己同样的问题,在阅读答案时,我发现选择也会影响到instanceof操作员.

由于抽象类是发送给JS的实际值,因此当子类扩展它时,它可用于运行时检查.

abstract class A {}

class B extends A {}

class C implements A {}

console.log(new B() instanceof A) // true
console.log(new C() instanceof A) // false
Run Code Online (Sandbox Code Playgroud)


小智 7

基于@ toskv的答案,如果扩展一个抽象类,则必须调用super()子类的构造函数.如果实现抽象类,则不必调用super()(但必须实现抽象类中声明的所有方法,包括私有方法).

如果要创建用于测试的模拟类而不必担心原始类的依赖项和构造函数,则实现抽象类而不是扩展它可能很有用.