Base and abstract classes
Base and abstract classes in JavaScript
Although JavaScript lacks the abstract
keyword, it's possible to create structures that mimic abstract (partially unimplemented) classes. This allows defining a common structure that must be implemented by child classes.
The purpose of abstract classes is to provide a common interface while leaving specific implementation to children.
In a regular base class, we can create methods that can be overridden by child classes.
class Animal { constructor(name) { this.name = name; }
speak() { console.log(${this.name} makes a sound); } }
Child classes can inherit and override the speak()
method according to their needs:
class Dog extends Animal { speak() { console.log(`${this.name} barks`); } }
const d = new Dog('Rex'); d.speak(); // Rex barks
Although JavaScript doesn't have special syntax for abstract classes, we can mimic them by forcing certain methods to be implemented by child classes.
class Shape { constructor() { if (this.constructor === Shape) { throw new Error("Abstract class 'Shape' cannot be instantiated directly."); } }
area() { throw new Error("Method 'area()' must be implemented."); } }
This prevents direct instantiation of Shape
objects:
const s = new Shape(); // Error: Abstract class 'Shape' cannot be instantiated directly.
Children must implement the area()
method:
class Rectangle extends Shape { constructor(w, h) { super(); this.w = w; this.h = h; }
area() { return this.w * this.h; } }
const r = new Rectangle(4, 5); console.log(r.area()); // 20
This structure is useful when you want to define a common structure while forcing children to implement certain methods.
JavaScript lacks interface
, but we can use JSDoc and static tools (like TypeScript or ESLint configurations) for interface validation.
For example:
/** * @interface ShapeInterface * @method area */
/**
@implements {ShapeInterface} */ class Circle { area() { return Math.PI * 2 ** 2; } }
Such annotations help IDEs and static analysis tools verify that a class implements the required interface.
Base and abstract classes in JavaScript allow creating a strong foundation for OOP design, even though the language lacks direct abstract
and interface
concepts. These approaches promote code reuse, safe addition of new classes, and adherence to OOP principles.
In the next part, we'll discuss applying SOLID principles in JavaScript OOP, specifically how each principle applies in real projects.