DEV Community

Cover image for JavaScript and Object Oriented Programming with its four pillar
Srishti Prasad
Srishti Prasad

Posted on • Updated on

JavaScript and Object Oriented Programming with its four pillar

The Principles of Object Oriented Programming (OOP)

The four fundamental OOP principles are encapsulation, abstraction polymorphism and inheritance.
I covered the four pillars of object-oriented programming in this article, with a special focus on inheritance and polymorphism using coded examples.

First let's understand how to create classes in JavaScript

Creating Classes

Consider that you need to code a Train class.
Once you've written this class, you'll be able to create objects of the Train class by using the keyword new.

class Train {}
Enter fullscreen mode Exit fullscreen mode

The constructor will be used to build properties on the future object instance of the Train class.

class Train {
    constructor() {

    }
}
Enter fullscreen mode Exit fullscreen mode

A common method of creating objects from classes is to use the Object.create() method

class Animal { /* ...class code here... */ }
var myDog = Object.create(Animal)
console.log (Animal)
Enter fullscreen mode Exit fullscreen mode

It can also be done using the newkeyword. JavaScript automatically invokes the Object superclass when using a default or empty function Object() { [native code] } method to build the instance.

class Animal { /* ...class code here... */ }
var myDog = new Animal()
console.log (Animal)
Enter fullscreen mode Exit fullscreen mode

Let's assume for the time being that each object instance of the Train class should only have the properties color and lightsOn when instantiated

class Train {
    constructor(color, lightsOn) {
        this.color = color;
        this.lightsOn = lightsOn;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now, to actually build a new instance of the Train class,

`var myFirstTrain = new Train('red', false);`
Enter fullscreen mode Exit fullscreen mode

However, this is not all that classes can offer, it's discussed further in detail in this blog.
You can also add methods to classes, and these methods will then be shared by all future instance objects of my Trainclass.

NOTE: this keyword it's the future object instance of the Train class.

Four pillars of OOP

Encapsulation

Encapsulation, in its most basic form, is the process of "hiding" a code implementation from other users so that they can "consume" it without having to understand how it operates.

"abc".toUpperCase()
Enter fullscreen mode Exit fullscreen mode

I shouldn't worry or even waste time trying to understand how the toUpperCase() method functions. Since I am aware that I have access to it, all I want to do is use it. I don't have to care about what it does in the background or even how it does it as long as it doesn't break my code, even if the underlying grammar, that is, how the toUpperCase() method is implemented, changes.

Abstraction

Writing code in a way that will make it more generic is the essence of abstraction.
Because of how difficult it may be to distinguish between encapsulation and abstraction, these ideas are frequently misunderstood.
It helps to think of it in the following terms:
The goal of an abstraction is to deal with the concept of what you're trying to do rather than a particular presentation of that concept.
Encapsulation is the process of preventing you from seeing or caring about an implementation's internal workings.

Polymorphism

Polymorphism means "multiple forms". An alternative translation might be: "something that can take on many shapes".

const bicycle = {
    bell: function() {
        return "Ring, ring! Watch out, please!"
    }
}
const door = {
    bell: function() {
        return "Ring, ring! Come here, please!"
    }
}
bicycle.bell(); // "Get away, please"
door.bell(); // "Come here, please"
Enter fullscreen mode Exit fullscreen mode

Here's another example,the concatenation operator, used by calling the built-in concat() method.
If I use the concat() method on two strings, it behaves exactly the same as if I used the + operator.

"abc".concat("def"); // 'abcdef'
["abc"].concat(["def"]); // ['abc', 'def']
["abc"] + ["def"]; // ["abcdef"]
Enter fullscreen mode Exit fullscreen mode

This means that the concat() method is exhibiting polymorphic behaviour since it behaves differently based on the context - in this case, based on what data types I give it.
To recap, polymorphism is advantageous because it enables programmers to create objects with identical functionality, i.e., functions with identical names that operate identically. In some other areas of the OOP framework, you can, however, change some portions of the shared code or even the entire functionality.

Inheritance

Inheritance is one of the foundations of object-oriented programming.
It's a fairly straightforward idea. It functions as follows: A "thing" base class exists.
The characteristics of the base class are inherited by one or more subclasses of "things" (sometimes also referred to as the "super-class")
Other sub-sub-classes of "things" that inherit from those classes may exist.
Keep in mind that every subclass derives from its superclass. In turn, a sub-class may also be a super-class if other classes are descended from it.

class Animal { /* ...class code here... */ }
class Bird extends Animal { /* ...class code here... */ }
class Eagle extends Bird { /* ...class code here... */ }
Enter fullscreen mode Exit fullscreen mode

It is possible to implement polymorphism using classes in JavaScript, by inheriting from the base class and then overridingthe inherited behavior.
To inherit from one class to a new sub-class, JavaScript provides the extends keyword,

class HighSpeedTrain extends Train {
}
Enter fullscreen mode Exit fullscreen mode

In the code that follows, you will observe another class being coded, which is named HighSpeedTrain and inherits from the Train class.
This makes the Train class a base class, or the super-class of the HighSpeedTrain class. Put differently, the HighSpeedTrain class becomes the sub-class of the Train class, because it inherits from it.
To inherit from one class to a new sub-class, JavaScript provides the extends keyword, which works as follows:
To inherit from one class to a new sub-class, JavaScript provides the extends keyword,

class HighSpeedTrain extends Train {
    constructor(passengers, highSpeedOn, color, lightsOn) {
        super(color, lightsOn);
        this.passengers = passengers;
        this.highSpeedOn = highSpeedOn;
    }
    toggleHighSpeed() {
        this.highSpeedOn = !this.highSpeedOn;
        console.log('High speed status:', this.highSpeedOn);
    }
}

Enter fullscreen mode Exit fullscreen mode

Notice the slight difference in syntax in the constructor of the HighSpeedTrain class, namely the use of the super keyword.
In JavaScript classes, super is used to specify what property gets inherited from the super-class in the sub-class.
In this case, I choose to inherit both the properties from the Train super-class in the HighSpeedTrain sub-class.
Notice that in addition to the inherited properties, you also automatically inherit all the methods that exist on the Train prototype, namely, the toggleLights(), lightsStatus()methods.

Additionally, imagine you realized that you don't like how the toggleLights() method from the super-class works, and you want to implement it a bit differently in the sub-class. You can add it inside the HighSpeedTrain class.

class HighSpeedTrain extends Train {
    constructor(passengers, highSpeedOn, color, lightsOn) {
        super(color, lightsOn);
        this.passengers = passengers;
        this.highSpeedOn = highSpeedOn;
    }
    toggleHighSpeed() {
        this.highSpeedOn = !this.highSpeedOn;
        console.log('High speed status:', this.highSpeedOn);
    }
    toggleLights() {
        super.toggleLigths();
        super.lightsStatus();
        console.log('Lights are 100% operational.');
    }
}

Enter fullscreen mode Exit fullscreen mode

So, how did you override the behavior of the original toggleLights() method?
Well in the super-class, the toggleLights() method

toggleLights() {
    this.lightsOn = !this.lightsOn;
}
Enter fullscreen mode Exit fullscreen mode

You realized that the HighSpeedTrain method should reuse the existing behavior of the original toggleLights() method, and so you used the super.toggleLights() syntax to inherit the entire super-class' method.
Next, you also inherit the behavior of the super-class' lightsStatus() method - because you realize that you want to have the updated status of the lightsOn property logged to the console, whenever you invoke the toggleLights() method in the sub-class.

var trainOne = new Train('blue', false);
var highSpeedy = new HighSpeedTrain(200, false, 'green', false);
Enter fullscreen mode Exit fullscreen mode

You've built the trainOne object of the Train class, and set its color to "blue" and its lightsOn to false.

Next, you've built the highSpeedy object to the HighSpeedTrain class, setting passengers to 200, highSpeedOn to false, color to "green", and lightsOn to false.

If you have any query let me know in the comment section. I'll try my best to answer them.
If you find this blog helpful, please ❤️ like it.
You can follow me if you wish to enhance your fundamental knowledge of JavaScript
In the coming blogs I'll be covering most asked concepts of JavaScript.

Top comments (0)