Abstract Classes in TypeScript

Abstract classes in TypeScript are classes that cannot be instantiated directly. They are meant to be extended by other classes. An abstract class can contain both abstract methods (methods without implementation) and regular methods with implementation. Abstract classes provide a blueprint for other classes to follow.

 

Key Points About Abstract Classes:

  1. Cannot be instantiated: You cannot create an object of an abstract class directly.
  2. Abstract methods: These methods do not have a body and must be implemented by subclasses.
  3. Regular methods: Abstract classes can also have regular methods with full implementations.
  4. Used for inheritance: They are designed to be extended by other classes that implement the abstract methods.

 

Declaring an Abstract Class

An abstract class is declared using the abstract keyword before the class keyword. Abstract methods are declared using the abstract keyword inside the class.

Example:

abstract class Animal {
  // Abstract method
  abstract speak(): void;

  // Regular method
  move(): void {
    console.log("The animal moves.");
  }
}

class Dog extends Animal {
  // Implementing the abstract method
  speak(): void {
    console.log("The dog barks.");
  }
}

const dog = new Dog();
dog.speak();  // Output: The dog barks.
dog.move();   // Output: The animal moves.

In this example:

  • The Animal class is abstract and contains one abstract method speak() and one regular method move().
  • The Dog class extends Animal and provides an implementation for the speak() method.
  • We can create an instance of Dog, but not of Animal, because Animal is abstract.

Abstract Methods

Abstract methods are defined in the abstract class without a body. These methods must be implemented in the derived class.

Example:

abstract class Vehicle {
  abstract startEngine(): void;  // Abstract method

  move(): void {
    console.log("The vehicle moves.");
  }
}

class Car extends Vehicle {
  startEngine(): void {  // Implementing abstract method
    console.log("The car engine starts.");
  }
}

const car = new Car();
car.startEngine();  // Output: The car engine starts.
car.move();         // Output: The vehicle moves.

In this example:

  • The Vehicle class contains an abstract method startEngine(), which must be implemented by any class that extends Vehicle.
  • The Car class provides an implementation for the startEngine() method.

Abstract Class with Constructor

Abstract classes can also have constructors, and these constructors can be called by the derived class using the super keyword.

Example:

abstract class Shape {
  constructor(public color: string) {}

  abstract getArea(): number;
}

class Circle extends Shape {
  constructor(color: string, public radius: number) {
    super(color);  // Calling the constructor of the abstract class
  }

  getArea(): number {
    return Math.PI * this.radius * this.radius;
  }
}

const circle = new Circle("red", 5);
console.log(circle.color);   // Output: red
console.log(circle.getArea());  // Output: 78.53981633974483

In this example:

  • The Shape class has a constructor that takes a color parameter.
  • The Circle class extends Shape and calls the super(color) constructor to initialize the color property.
  • The getArea() method is implemented in the Circle class.

Abstract Classes and Interfaces

An abstract class can implement interfaces, just like any other class. It can provide implementation for the methods of the interface, or it can leave them as abstract methods to be implemented by the derived class.

Example:

interface Movable {
  move(): void;
}

abstract class Vehicle implements Movable {
  abstract move(): void;  // Implementing the interface method as abstract

  startEngine(): void {
    console.log("Engine started.");
  }
}

class Bike extends Vehicle {
  move(): void {  // Implementing the move method
    console.log("The bike moves.");
  }
}

const bike = new Bike();
bike.move();      // Output: The bike moves.
bike.startEngine();  // Output: Engine started.

In this example:

  • The Vehicle class implements the Movable interface but leaves the move() method abstract.
  • The Bike class extends Vehicle and provides an implementation for the move() method.

 

Summary

Abstract classes in TypeScript are used to define a base class that cannot be instantiated directly. They are meant to be extended by other classes, and they can include abstract methods that must be implemented by subclasses. Key points about abstract classes include:

  • Abstract methods: Methods without implementations that must be implemented in subclasses.
  • Regular methods: Methods with implementations that can be inherited by subclasses.
  • Cannot be instantiated: You cannot create an object of an abstract class.
  • Inheritance: Abstract classes are meant to be extended by other classes.

Abstract classes are useful when you want to define a common structure or functionality for all subclasses while leaving certain details to be filled in by the subclasses.