Welcome to Abstraction

Welcome back! Previously, you explored polymorphism and how it empowers you to create flexible code structures using inheritance. In this session, we will take a step further into a crucial aspect of object-oriented programming: Abstraction.

Understanding Abstraction in JavaScript

While JavaScript does not natively support abstract classes like some other programming languages, modern JavaScript provides mechanisms to simulate this behavior. You can create a structure that enforces method implementations in derived classes, thereby achieving abstraction.

1. Simulating an Abstract Class

To simulate abstract classes in JavaScript, we can utilize ES6 class syntax and create methods that throw errors when not overridden:

// Create a base class Shape that simulates an abstract class
class Shape {
    constructor(color) {
        this.color = color;
    }

    // Simulate abstract methods by throwing an error if they are not implemented
    area() {
        throw new Error('Method "area()" must be implemented');
    }

    perimeter() {
        throw new Error('Method "perimeter()" must be implemented');
    }

    // Concrete method to get the color
    getColor() {
        return this.color;
    }
}

In this JavaScript class Shape, we define a constructor and a method getColor. The area and perimeter functions throw errors if not overridden, simulating the behavior of abstract methods. This approach enforces that any subclass must provide implementations for these methods.

2. Implementing the Methods in Derived Classes

Now, let’s create concrete classes that extend the base class Shape:

Circle Class
// Define a Circle class that extends Shape
class Circle extends Shape {
    constructor(radius, color) {
        super(color);
        this.radius = radius;
    }

    // Implement the area and perimeter methods
    area() {
        return Math.PI * this.radius * this.radius;
    }

    perimeter() {
        return 2 * Math.PI * this.radius;
    }
}

The Circle class inherits from Shape and implements the area and perimeter methods. We also provide a constructor to initialize the circle's radius and color, passing the color to the parent class constructor using super.

Rectangle Class
// Define a Rectangle class that extends Shape
class Rectangle extends Shape {
    constructor(width, height, color) {
        super(color);
        this.width = width;
        this.height = height;
    }

    // Implement the area and perimeter methods
    area() {
        return this.width * this.height;
    }

    perimeter() {
        return 2 * (this.width + this.height);
    }
}

Similarly, the Rectangle class extends Shape, implementing the area and perimeter methods and initializing attributes through its constructor.

3. Using the Base Class and Derived Classes
Why It Matters

Simulating abstraction in JavaScript enables you to enforce patterns and rules within your codebase. It ensures that derived classes implement critical functionality, maintaining uniformity across implementations.

By mastering these techniques:

  1. Create more organized and readable code: Clear structures enforce method behaviors.
  2. Encourage code reusability: Common functionality resides in base classes, preventing redundant code.
  3. Enhance flexibility: Easily extend functionality without altering existing code, adhering to fundamental software design principles.

Intrigued? Let's move on to the practice section and solidify these concepts together. You're on your way to becoming proficient in building sophisticated and maintainable systems with JavaScript!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal