Suppose I have a pure abstract class (that is, an abstract class without any implementation):
abstract class A {
abstract m(): void;
}
Like in C# and Java, I can extend the abstract class:
class B extends A {
m(): void { }
}
But unlike in C# and Java, I can also implement the abstract class:
class C implements A {
m(): void { }
}
How do classes B
and C
behave differently? Why would I choose one versus the other?
(Currently, the TypeScript handbook and language specification don't cover abstract classes.)
The implements keyword treats the A class as an interface, that means C has to implement all the methods defined in A, no matter if they have an implementation or not in A. Also there are no calls to super methods in C.
extends behaves more like what you'd expect from the keyword. You have to implement only the abstract methods, and super calls are available/generated.
I guess that in the case of abstract methods it does not make a difference. But you rarely have a class with only abstract methods, if you do it would be much better to just transform it to an interface.
You can easily see this by looking at the generated code. I made a playground example here.
I was led here because I had just been asking myself the same question and while reading the answers it ocurred to me that the choice will also affect the instanceof
operator.
Since an abstract class is an actual value that gets emitted to JS it can be used for runtime checks when a subclass extends it.
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
Building on @toskv's answer, if you extend an abstract class, you have to call super()
in the subclass's constructor. If you implement the abstract class, you don't have to call super()
(but you have to implement all the methods declared in the abstract class, including private methods).
Implementing an abstract class instead of extending it could be useful if you want to create a mock class for testing without having to worry about the original class's dependencies and constructor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With