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


76

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

abstract class A {
    abstract m(): void;
}

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

class B extends A {
    m(): void { }
}

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

class C implements A {
    m(): void { }
}

BC行为如何不同?为什么我要选择一个?

(当前,TypeScript手册语言规范不涵盖抽象类。)


1
现在,TypeScript手册中有一个有关抽象类的部分。 typescriptlang.org/docs/handbook/classes.html 感谢您提出的问题!我不知道abstractTS中有没有可用的方法,这有助于我理解它。
theUtherSide

由@theUtherSide链接的文档以某种方式没有一个单一的示例,这真是令人惊讶class C implements A。在阅读这些文章之前,我什至不知道这是有可能的,而且最近我在ts文档中访问了很多
凯文斯(Kevins)

Answers:


98

工具关键字对待A类为一个接口,这意味着C具有实现所有A中所定义的方法,不管他们是否有在执行或不一个。也没有在C中调用super方法。

extend的行为更像您希望从关键字获得的内容。您仅需实现抽象方法,并且超级调用可用/已生成。

我猜想在抽象方法的情况下没有什么区别。但是,您很少有只包含抽象方法的,如果这样做,将其转换为接口会更好。

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


12
如果A是纯抽象类,也许唯一可观察到的区别就是instanceof关键字的行为?我同意接口可能比纯抽象类更好。但是,在Angular 2中,只有后者可以用作DI提供程序令牌。
Michael Liu

1
确实,感谢您发现了instanceof事物,我将其添加到完成答案中(如果需要,您可以进行编辑)。至于angular2,我想这是angular2的特定问题。:)
toskv '16

2
@toskv,感谢您描述'implements'关键字对接口AND类的适用性。例如,AngularJS 2.0使用它来实现其“ OnInit” CLASS(而不是“ interface”)。我环顾四周,您对此有参考吗?我在TS文档中看不清。
MoMo


18

我之所以被带到这里,是因为我一直在问自己同样的问题,并且在阅读答案时发现,选择也会影响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

谢谢@陶,这是一个纯正的,很好的解释。我也想为此添加额外的信息,是否删除抽象关键字并不重要,如果删除抽象关键字,您将获得相同的结果。
Dogan

10

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

如果要创建一个模拟类进行测试而不必担心原始类的依赖项和构造函数,则实现一个抽象类而不是对其进行扩展可能会很有用。


0

在您提供的扩展示例中,实际上并未向该类添加任何新内容。因此,它没有任何扩展。尽管无所事事的扩展是有效的Typescript,但在我看来,在这种情况下,“实现”会更合适。但最终,它们是等效的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.