Inheritance and polymorphism in ECMAScript (ES6)

View more Tutorials:

1- Inheritance in ECMAScript

Before you start learning about "Inheritance in ECMAScript", make sure you have the concept of "Class and object", if not, let's learn it:
ECMAScript allows you to create a class extended from one or more other classes. This class is called a derived class, or a subclass.
A child class will inherit properties, methods, and other members from a parent class. It can also override methods from the parent class. In ECMAScript, each class has only one constructor. If a class itself does not define its own constructor, it inherits the constructor of the parent class. Contrarily, if the child class defines a constructor, it will not inherit the constructor of the parent class.
Unlike Java, CSharp and several other languages, ECMAScript allows multiple inheritance. A class can be extended from one or more parent classes.
We need a few classes to participate in examples.
  • Animal: Class simulate an animal.
  • Duck: Subclass of Animal.
  • Cat: Subclass of Animal.
  • Mouse: Subclass of Animal.
In ECMAScript, constructor of class used to create an object (instance), and assign the value for the properties. Constructor of subclasses always called to a constructor of parent class to initialize value for the properties in the parent class, then it assign value for its properties.
Example:
Cat is the class that inherits from the Animal class, it also has its properties.
inherit-example1.js
class Animal {

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

   showInfo()  {
     console.log("I'm " + this.name);
   }

   move()  {
     console.log("Moving..");
   }

}

class Cat extends Animal {
    constructor(name, age, height) {
       super(name);
       // Cat's properties:
       this.age = age;
       this.height = height;
    }

    // Override method of parent class.
    showInfo()  {
      console.log("My name is " + this.name);
    }

    // Other method...
    sleep()  {
       console.log("Sleeping..");
    }
}

// ------------- TEST --------------------
let tom = new Cat("Tom", 3, 20);

console.log("Call move() method");

tom.move();

console.log("\n");
console.log("Call showInfo() method");

tom.showInfo();
What's happened when you create an object from constructor . How does it call up a constructor of the parent class? Please see the illustration below:
With the above illustration you see that, constructor of  parent class is called in constructor of  subclass, it will assign values to the properties of the parent class, then the properties of the subclass.

2- Override method

By default, child classes inherit methods from the parent class, but parent classes can override the method of the parent class.
inheritance-example2.js
class Animal {

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

   showInfo()  {
     console.log("I'm " + this.name);
   }

   move()  {
     console.log("Moving..");
   }

}

class Mouse extends Animal {

    constructor(name, age, height) {
       super(name);

       this.age = age;
       this.height = height;
    }

    // Override method of parent class.
    showInfo()  {
      // Call showInfo() method of parent class.
      super.showInfo();
      console.log ("Age: " + this.age);
      console.log ("Height: " + this.height);
    }

    // Override method of parent class.
    move()  {
      console.log("Mouse Moving..");
    }
}

// ------------- TEST --------------------
let jerry = new Mouse("Jerry", 3, 5);

console.log("Call move() method");

jerry.move();

console.log("\n");
console.log("Call showInfo() method");

jerry.showInfo();

3- Abstract Method

The concept of an abstract method or abstract class is defined in languages such as Java, C#. But it is not clearly defined in ECMAScript. However, we have a way to define it.
A class called as abstract defines abstract methods and child class must override these methods if you want to use them. The abstract methods always throw the exception "Not Implemented Error".
abstract-example.js
// An abstract class.
class AbstractDocument {

    constructor(name) {
        this.name = name
    }

    // A method can not be used, because it always throws an error.
    show() {
        // Not Implemented Error
        throw "Subclass must implement abstract method";
    }
}

class PDF extends AbstractDocument {

    // Override method of parent class
    show() {
        console.log("Show PDF document:", this.name);
    }
}



class Word extends AbstractDocument {
    show() {
        console.log("Show Word document:", this.name)
    }
}



// -------------------- TEST -------------------------
let doc1 = new PDF("Python tutorial");
let doc2 = new Word("Java IO Tutorial");
let doc3 = new PDF("ECMAScript Date & Time Tutorial");

let documents = [doc1, doc2, doc3];


for (let i = 0; i < documents.length; i++) {
    documents[i].show();
}

let doc4 = new AbstractDocument("An Abstract Document");

doc4.show(); // Throw Error!!!
The example above demonstrates Polymorphism in ECMAScript. A Document object can be represented in various forms (PDF, Word, Excel, ...).
Another example illustrates polymorphism: When I talk about an Asian people, it's quite abstract, he can be Japanese, Vietnamese, or Indian. However, there are features of Asian people.

4- Operators - instanceof, typeof

instanceof

The instanceof operator helps you to check whether "something" is an object of a certain class or not.
instanceof-example.js
class Person {

}

// A Child class of Person
class AsianPerson extends Person {

}

class Triangle {

}

let person = new Person();
let asianPerson = new AsianPerson();

let triangle = new Triangle();

let isPerson = person instanceof Person;
console.log( isPerson ); // true

console.log( asianPerson instanceof Person ); // true

console.log( person instanceof AsianPerson ); // false
console.log( triangle instanceof Person ); // false
console.log( triangle instanceof AsianPerson ); // false

typeof

The typeof operator is used to check the type of "something". The result obtained is the name of the type.
Type Result
undefined "undefined"
null "object"
boolean "boolean"
number "number"
String "string"
Symbol (new in ECMAScript 6) "symbol"
Host object (provided by the JS environment) Implementation-dependent
Function object (implements [[Call]] in ECMA-262 terms) "function"
Any other object "object"
typeof-example.js
// A Class:
class Person {

}
// An Object:
let person = new Person();

console.log( typeof Person ); // function
console.log( typeof person ); // object

// null:
console.log( typeof null ); // object

// A Number:
let intValue = 100;

console.log( typeof intValue ); // number

// NaN (Not a Number)
console.log( typeof NaN); // number

// A String
let strValue = "Hello";

console.log( typeof strValue ); // string

// A Boolean:
let boolValue = true;

console.log( typeof boolValue ); // boolean

// undefined
console.log( typeof undefined); // undefined

// An Array
let years = [1980, 2003, 2018];

console.log( typeof years ); // object

// A Function
let myFunc = function()  {

}

console.log( typeof myFunc ); // function

// A Symbol
let mySymbol =   Symbol();

console.log( typeof mySymbol ); // symbol

Is Sub Class?

Suppose you have two classes, A & B. The following example  helps you check whether A is a child class of B or not.
let isChild = A === B || A.prototype instanceof B;
issubclass-example.js
class Animal {

}

class Cat extends Animal {
 
}

class AsianCat extends Cat {

}

// ------------- TEST --------------------

console.log("AsianCat === Animal? " + (AsianCat === Animal)); // false

let isSubClass1 = AsianCat === Animal || AsianCat.prototype instanceof Animal;

console.log("AsianCat is child of Animal? " + isSubClass1); // true

let isSubClass2 = AsianCat === Animal || Animal.prototype instanceof AsianCat;

console.log("Animal is child of AsianCat? " + isSubClass2); // false

 

5- Polymorphism with function

The languages such as Java, C# are very close about data types. Therefore, when you call a method (function), you have to pass the correct data type corresponding to parameters. In ECMAScript, when calling a function, you can pass parameters with any data type, A risk may occur, and a developer has to manage such risks by himself/herself.
Here I create two classes such as English and French. Both of the classes have the greeting() method. Both create different greetings. Create two corresponding objects from the two classes above and call the actions of these two objects in the same function ( intro function).
polymorphism-example.js
class English {

    greeting() {
        console.log("Hello");
    }
}

class French {
    greeting() {
        console.log("Bonjour");
    }
}

function intro(language) {
    language.greeting();
}

// -------------- TEST ----------------------

let flora = new English();
let aalase = new French();

// Call function:
intro(flora);
intro(aalase);

let someObject = {};

intro(someObject);// Error!!!
Run the example:
OK, Correct the code of the above example, add necessary checks to avoid risks for your application:
polymorphism-example2.js
class English {

    greeting() {
        console.log("Hello");
    }
}

class French {
    greeting() {
        console.log("Bonjour");
    }
}

function intro(language) {
    // Check type of 'language' object.
    if(language instanceof English || language instanceof French)  {
      language.greeting();
    }
}

// -------------- TEST ----------------------

let flora = new English();
let aalase = new French();

// Call function:
intro(flora);
intro(aalase);

let someObject = {};

intro(someObject);
Applying the "Classes & Inheritance" architecture helps your application be easier to be managed and avoid errors.
polymorphism-example3.js
// A Base class
class Language {

}
class English extends Language {

    greeting() {
        console.log("Hello");
    }
}

class French  extends Language {
    greeting() {
        console.log("Bonjour");
    }
}

function intro(language) {
    // Check type of 'language' object.
    if(language instanceof Language)  {
      language.greeting();
    }
}

// -------------- TEST ----------------------

let flora = new English();
let aalase = new French();

// Call function:
intro(flora);
intro(aalase);

let someObject = {};

intro(someObject);
See also:

View more Tutorials: