If you take Erics answer a little further you can actually create a pretty decent implementation of abstract classes, with full support for polymorphism and the ability to call implemented methods from the base class. Let's start with the code:
/**
* The interface defines all abstract methods and extends the concrete base class
*/
interface IAnimal extends Animal {
speak() : void;
}
/**
* The abstract base class only defines concrete methods & properties.
*/
class Animal {
private _impl : IAnimal;
public name : string;
/**
* Here comes the clever part: by letting the constructor take an
* implementation of IAnimal as argument Animal cannot be instantiated
* without a valid implementation of the abstract methods.
*/
constructor(impl : IAnimal, name : string) {
this.name = name;
this._impl = impl;
// The `impl` object can be used to delegate functionality to the
// implementation class.
console.log(this.name + " is born!");
this._impl.speak();
}
}
class Dog extends Animal implements IAnimal {
constructor(name : string) {
// The child class simply passes itself to Animal
super(this, name);
}
public speak() {
console.log("bark");
}
}
var dog = new Dog("Bob");
dog.speak(); //logs "bark"
console.log(dog instanceof Dog); //true
console.log(dog instanceof Animal); //true
console.log(dog.name); //"Bob"
Since the Animal
class requires an implementation of IAnimal
it's impossible to construct an object of type Animal
without having a valid implementation of the abstract methods. Note that for polymorphism to work you need to pass around instances of IAnimal
, not Animal
. E.g.:
//This works
function letTheIAnimalSpeak(animal: IAnimal) {
console.log(animal.name + " says:");
animal.speak();
}
//This doesn't ("The property 'speak' does not exist on value of type 'Animal')
function letTheAnimalSpeak(animal: Animal) {
console.log(animal.name + " says:");
animal.speak();
}
The main difference here with Erics answer is that the "abstract" base class requires an implementation of the interface, and thus cannot be instantiated on it's own.