Inheritance vs Composition

Object-oriented programming (OOP) is a popular paradigm that encourages modular, reusable, and maintainable code. Two fundamental concepts within OOP are inheritance and composition. While both play crucial roles in designing software systems, they offer distinct approaches to code organization and reuse. In this article, we'll delve into the key differences between inheritance and composition in TypeScript, providing illustrative examples and real-world use cases for each.

Understanding Inheritance

Inheritance is a fundamental concept in OOP that enables one class (the child or subclass) to inherit properties and methods from another class (the parent or superclass). This mechanism promotes code reuse by allowing the child class to extend the behaviour of the parent class. In TypeScript, inheritance is achieved using the extends keyword.

Example: Inheriting Properties and Methods

Let's consider a classic example involving shapes. We have a base class Shape and a subclass Circle that inherits from it.

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

    draw(): void {
        console.log(`Drawing a ${this.color} shape`);
    }
}

class Circle extends Shape {
    constructor(color: string, private radius: number) {
        super(color);
    }

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

In this example, Circle inherits the color property and the draw method from Shape and it also defines its method calculateArea.

Embracing Composition

Composition is an alternative approach to code reuse that involves constructing complex objects by combining smaller, more specialized objects. Unlike inheritance, which creates a tight coupling between parent and child classes, composition promotes greater flexibility and modularity. TypeScript facilitates composition through the use of class properties and interfaces.

Example: Composing Complex Objects

Let's consider a scenario where we need to model a Person class that has an associated Address object.

class Address {
    constructor(public street: string, public city: string, public zip: string) {}
}

class Person {
    constructor(public name: string, public age: number, public address: Address) {}

    displayInfo(): void {
        console.log(`${this.name} is ${this.age} years old and lives in ${this.address.city}`);
    }
}

In this example, the Person class is composed of an Address object, promoting a more modular and loosely coupled design.

Choosing the Right Approach: Use Cases

Inheritance Use Cases

Inheritance is suitable when you want to:

  1. Extend Behavior: You want to create a specialized version of an existing class, adding or modifying its behaviour. For instance, creating different types of shapes based on a common shape class.

  2. Promote Code Reuse: You intend to reuse a significant portion of code from a base class across multiple subclasses.

Composition Use Cases

Composition shines when:

  1. Flexibility is Key: You need to build complex objects with varying parts that can be easily swapped out or modified without affecting the entire structure.

  2. Avoid Tight Coupling: You want to avoid creating deep hierarchies and tight dependencies between classes, leading to more maintainable and modular code.

Conclusion and Further Readings

Inheritance and composition are two powerful techniques in TypeScript's object-oriented toolbox. Each approach has its strengths and use cases, allowing developers to craft software systems that balance code reuse, modularity, and flexibility. By understanding the differences between inheritance and composition, you can make informed design decisions that lead to robust and adaptable software architectures.

https://www.geeksforgeeks.org/difference-between-composition-and-inheritance-in-javascript/

https://www.newline.co/books/beginners-guide-to-typescript/inheritance-and-composition

https://softchris.github.io/pages/javascript-composition.html

Did you find this article valuable?

Support Divij Sehgal by becoming a sponsor. Any amount is appreciated!