OOP/OOD  

Chapter 15: Object-Oriented Programming (OOP) with Classes

Object-Oriented Programming (OOP) is a programming paradigm based on the concept of "objects," which can contain data (attributes or properties) and code (methods or functions). JavaScript uses ES6 Classes as a cleaner, syntactical way to implement traditional object-oriented patterns like inheritance and encapsulation, building upon the prototype model.

1. Defining a Class

A class is essentially a blueprint for creating objects. Use the class keyword.

JavaScript

class Vehicle {
    // The constructor is a special method for creating and initializing an object
    constructor(make, model, year) {
        this.make = make;
        this.model = model;
        this.year = year;
        this.isRunning = false; // Default property
    }

    // A method (a function defined within the class)
    start() {
        this.isRunning = true;
        console.log(`${this.make} ${this.model} is now running.`);
    }

    // Another method
    stop() {
        this.isRunning = false;
        console.log(`${this.model} is stopped.`);
    }
}

// Creating a new instance (object) from the class
const myCar = new Vehicle('Toyota', 'Camry', 2020);
myCar.start(); // Output: Toyota Camry is now running.

2. Inheritance (extends and super)

Inheritance allows you to create a new class (Child/Derived Class) that inherits properties and methods from an existing class (Parent/Base Class), promoting code reuse.

  • The extends keyword is used to inherit from a parent class.

  • The super() method must be called in the child's constructor to call the parent's constructor and initialize the properties defined there.

JavaScript

class Car extends Vehicle {
    constructor(make, model, year, fuelType) {
        super(make, model, year); // Call the parent (Vehicle) constructor
        this.fuelType = fuelType;
    }

    // Overriding a parent method
    start() {
        super.start(); // Call the parent's start method first
        console.log(`Checking ${this.fuelType} level...`);
    }

    // New method specific to the Car class
    honk() {
        console.log('Beep beep!');
    }
}

const civic = new Car('Honda', 'Civic', 2023, 'Gasoline');
civic.start(); // Calls the Car's start method, which calls Vehicle's start.
civic.honk();

3. Static Methods

Static methods are methods defined on the class itself, not on instances of the class. They are often used as utility functions that are specific to the class but don't need access to the instance's data (this).

JavaScript

class Calculator {
    static add(a, b) {
        return a + b;
    }

    static multiply(a, b) {
        return a * b;
    }
}

// Call directly on the class, not an instance
const sum = Calculator.add(5, 3); // Output: 8
// const instance = new Calculator(); instance.add() // This would fail

4. Getters and Setters

Getters and Setters allow you to treat class methods like properties. They provide a layer of encapsulation by allowing you to control how properties are accessed and modified.

JavaScript

class Product {
    constructor(price) {
        this._price = price; // Use a leading underscore for private-like properties
    }

    // Getter: Runs code when reading the .price property
    get price() {
        // You could add complex logic here, e.g., currency conversion
        return this._price;
    }

    // Setter: Runs code when assigning to the .price property
    set price(newPrice) {
        if (newPrice < 0) {
            throw new Error("Price cannot be negative.");
        }
        this._price = newPrice;
    }
}

const item = new Product(100);
item.price = 150; // Calls the setter
console.log(item.price); // Calls the getter (Output: 150)