假设我有一个纯抽象类(即没有任何实现的抽象类):
abstract class A {
abstract m(): void;
}
与C#和Java一样,我可以扩展抽象类:
class B extends A {
m(): void { }
}
但与C#和Java中的不同,我还可以实现抽象类:
class C implements A {
m(): void { }
}
班级B
和C
的行为方式有何不同?为什么我会选择一个与另一个?
(目前,TypeScript handbook和language specification不会涵盖抽象类。)
答案 0 :(得分:63)
implements 关键字将A类视为接口,这意味着 C必须实现A 中定义的所有方法,无论它们是否具有实现在 A 。此外, C 中没有超级方法的调用。
扩展的行为更像您对该关键字的期望。您必须只实现抽象方法,并且可以使用/生成超级调用。
我想在抽象方法的情况下它并没有什么区别。但是你很少有一个只有抽象方法的类,如果你这样做,将其转换为接口会好得多。
通过查看生成的代码,您可以轻松看到这一点。我制作了一个游乐场示例here。
答案 1 :(得分:9)
我被带到这里是因为我刚问自己同样的问题,在阅读答案时,我发现选择也会影响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
答案 2 :(得分:6)
在@toskv's answer上构建,如果扩展抽象类,则必须在子类的构造函数中调用super()
。如果您实现抽象类,则不必调用super()
(但您必须实现抽象类中声明的所有方法,包括私有方法)。
如果要创建一个用于测试的模拟类而不必担心原始类的依赖项和构造函数,那么实现抽象类而不是扩展它可能很有用。
答案 3 :(得分:0)
在您提供的扩展示例中,您实际上并未向该类添加任何新内容。所以它什么都没有扩展。虽然无效延伸是有效的Typescript,但在我看来,在这种情况下,实现'会更合适。但在一天结束时他们是等同的。