Inheritance

Implementing JavaScript inheritance using extends and super

Prior to ES6, implementing a proper inheritance required multiple steps. One of the most commonly used strategies is the prototypal inheritance. The following illustrates how the Bird inherits properties from the Animal using the prototype inheritance technique.

function Animal(legs) {
    this.legs = legs;
}

Animal.prototype.walk = function() {
    console.log('walking on ' + this.legs + ' legs');
}

function Bird(legs) {
    Animal.call(this, legs);
}

Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Animal;


Bird.prototype.fly = function() {
    console.log('flying');
}

var pigeon = new Bird(2);
pigeon.walk(); // walking on 2 legs
pigeon.fly(); // flying

ES6 simplified these steps by using the extends and super keywords. The following example defines the Animal and Bird classes and establishes the inheritance through the extends and super keywords.

class Animal {
    constructor(legs) {
        this.legs = legs;
    }
    walk() {
        console.log('walking on ' + this.legs + ' legs');
    }
}

class Bird extends Animal {
    constructor(legs) {
        super(legs);
    }
    fly() {
        console.log('flying');
    }
}


let bird = new Bird(2);

bird.walk();
bird.fly();

In this example, the Bird‘s constructor uses super() to call the Animal‘s constructor with the specified arguments.

Note that the class version is just the syntactic sugar for the prototypal inheritance. In other words, JavaScript uses classes for the syntax but still realizes on the prototype mechanism

The Animal class is called base class and the Bird class is known as derived class. JavaScript requires the derived class to use super() if it has a constructor. As you see in the Bird class, the super(legs) is equivalent to the following statement.

Animal.call(this, legs);

If you decide to not use constructor in the Bird class, you can do it as follows:

class Bird extends Animal {
    fly() {
        console.log('flying');
    }
}

It is equivalent to the following class:

class Bird extends Animal {
    constructor(...args) {
        super(...args);
    }
    fly() {
        console.log('flying');
    }
}

However, if you specify the constructor, you muse call super() inside the constructor, therefore the following code results in an error.

class Bird extends Animal {
    constructor(legs) {
    }
    fly() {
        console.log('flying');
    }
}

Because the super() initializes the this object, you must call the super() before accessing the this object. Trying to access this before calling super() results in an error.

For example, if you want to initialize the color property of the Bird class, you can do it as follows:

class Bird extends Animal {
    constructor(legs, color) {
        super(legs);
        this.color = color;
    }
    fly() {
        console.log('flying');
    }
    getColor() {
        console.log(this.color);
    }
}


let pegion = new Bird(2, 'white');
console.log(pegion.getColor());

Shadowing methods

JavaScript allows you to add a new method in the derived class that has the same name as a method in the base class. In this case, when you call the method of an object of the derived class, that method will shadow the method in the base class.

The following Dog class extends the Animal class and redefines the walk() method.

class Dog extends Animal {
    constructor() {
        super(4);
    }
    walk() {
        console.log(`go walking`);
    }
}

let bingo = new Dog();
bingo.walk(); // go walking

To call the method of the base class in the derived class, you use super.method() like this:

class Dog extends Animal {
    constructor() {
        super(4);
    }
    walk() {
        super.walk();
        console.log(`go walking`);
    }
}

let bingo = new Dog();
bingo.walk();
// walking on 4 legs
// go walking

Inheriting static members

The derived class inherits all static members of the base class. See the following example.

class Animal {
    constructor(legs) {
        this.legs = legs;
    }
    walk() {
        console.log('walking on ' + this.legs + ' legs');
    }
    static helloWorld() {
        console.log('Hello World');
    }
}

class Bird extends Animal {
    fly() {
        console.log('flying');
    }
}

In this example, the Animal class has the helloWorld() static method and this method is available as Bird.helloWorld() and behaves the same as the Animal.helloWorld() method. See the following code:

Bird.helloWorld(); // Hello World

Inheriting from built-in types

JavaScript allows you to extend a built-in type such as Array, String, Map, and Set through inheritance. The following Queue class extends the Array reference type. The syntax is much cleaner than the Queue implemented using the constructor/prototype pattern.

class Queue extends Array {
    enqueue(e) {
        super.push(e);
    }
    dequeue() {
        return super.shift();
    }
    peek() {
        return !this.empty() ? this[0] : undefined;
    }
    empty() {
        return this.length === 0;
    }
}

var customers = new Queue();
customers.enqueue('A');
customers.enqueue('B');
customers.enqueue('C');

while (!customers.empty()) {
    console.log(customers.dequeue());
}

In this tutorial, you have learned how to implement JavaScript inheritance using the extends and super keywords.

原文地址:https://www.cnblogs.com/PrimerPlus/p/12912150.html