Object-Oriented Programming (OOP): Understand the 4 Pillars with Clear Examples

Paulo Messias - Oct 26 - - Dev Community

Hey dev! Today we’re going to talk about Object-Oriented Programming (OOP). This paradigm is essential for organizing data and behaviors using "objects". If you’re preparing for a job interview, mastering these concepts can make all the difference.

We’ll explore the four pillars of OOP in a clear and practical way, with examples that will help you understand everything easily.

What Is Object-Oriented Programming?

OOP is based on four main pillars:

  1. Encapsulation
  2. Inheritance
  3. Polymorphism
  4. Abstraction

Let’s take a closer look at each of these pillars with examples in JavaScript.

1. Encapsulation

Encapsulation is like storing your belongings in a box. You put everything you need inside and control who can access it. This helps protect the stored data and ensures that the internal state of the object remains secure.

Example:

class User {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }

    // Public method
    displayInfo() {
        return `${this.name}, ${this.age} years old`;
    }

    // Private method
    _checkAge() {
        return this.age >= 18 ? 'an adult' : 'a minor';
    }

    displayStatus() {
        return `${this.name} is ${this._checkAge()}.`;
    }
}

const user = new User('Alice', 22);
console.log(user.displayInfo()); // Alice, 22 years old
console.log(user.displayStatus()); // Alice is an adult
Enter fullscreen mode Exit fullscreen mode

In this example, _checkAge is a method that shouldn't be accessed directly. It’s used internally to help determine the user’s status while keeping the logic organized.

2. Inheritance

Inheritance allows a class (subclass) to inherit properties and methods from another class (superclass). This makes it easier to reuse code and create class hierarchies.

Example:

class Animal {
    constructor(name) {
        this.name = name;
    }

    makeSound() {
        return `${this.name} makes a sound.`;
    }
}

class Dog extends Animal {
    makeSound() {
        return `${this.name} barks.`;
    }
}

class Cat extends Animal {
    makeSound() {
        return `${this.name} meows.`;
    }
}

const myDog = new Dog('Rex');
const myCat = new Cat('Mia');

console.log(myDog.makeSound()); // Rex barks.
console.log(myCat.makeSound()); // Mia meows.
Enter fullscreen mode Exit fullscreen mode

Here, both Dog and Cat inherit from Animal. Each implements its own sound, demonstrating how inheritance allows for customized behaviors without duplicating code.

3. Polymorphism

Polymorphism is the ability of different objects to respond to the same method in different ways. This allows methods with the same name to have different behaviors depending on the type of object.

Example:

class Shape {
    area() {
        return 0;
    }
}

class Rectangle extends Shape {
    constructor(width, height) {
        super();
        this.width = width;
        this.height = height;
    }

    area() {
        return this.width * this.height;
    }
}

class Circle extends Shape {
    constructor(radius) {
        super();
        this.radius = radius;
    }

    area() {
        return Math.PI * Math.pow(this.radius, 2);
    }
}

const shapes = [new Rectangle(10, 5), new Circle(3)];

shapes.forEach(shape => {
    console.log(`Area: ${shape.area()}`);
});

// Output:
// Area: 50
// Area: 28.274333882308138
Enter fullscreen mode Exit fullscreen mode

In this case, both Rectangle and Circle have their own area methods, but calling the same method yields different results based on the shape type. This is polymorphism in action!

4. Abstraction

Abstraction is the process of hiding complex details and exposing only what is necessary. In OOP, this allows you to use objects without needing to understand all the intricacies of how they work.

Example:

class Car {
    constructor(brand, model) {
        this.brand = brand;
        this.model = model;
    }

    start() {
        console.log('Car started.');
    }

    stop() {
        console.log('Car stopped.');
    }
}

class ElectricCar extends Car {
    charge() {
        console.log('Electric car charging.');
    }
}

const myElectricCar = new ElectricCar('Tesla', 'Model 3');
myElectricCar.start(); // Car started.
myElectricCar.charge(); // Electric car charging.
Enter fullscreen mode Exit fullscreen mode

Here, the Car class provides basic methods, while ElectricCar adds the charging functionality. You can use the car without knowing how each part works — you just need to know how to start and charge it.

Conclusion

And there you have it! You now have a clearer understanding of the four pillars of Object-Oriented Programming: encapsulation, inheritance, polymorphism, and abstraction. These concepts are essential for writing more organized and maintainable code.

Keep practicing and applying these principles in your projects, and you’ll be well-prepared to tackle challenges in interviews and in your day-to-day as a developer!

. . . . . . . . . . . . . . . . . . . . . . . .