fixes
This commit is contained in:
parent
c3fadb7dc1
commit
c9eea4d0bf
3 changed files with 22 additions and 52 deletions
|
@ -1,9 +1,13 @@
|
|||
|
||||
# Class inheritance
|
||||
|
||||
Let's say we have two classes.
|
||||
Class inheritance is a way for one class to extend another class.
|
||||
|
||||
`Animal`:
|
||||
So we can create new functionality on top of the existing.
|
||||
|
||||
## The "extends" keyword
|
||||
|
||||
Let's say with have class `Animal`:
|
||||
|
||||
```js
|
||||
class Animal {
|
||||
|
@ -24,52 +28,19 @@ class Animal {
|
|||
let animal = new Animal("My animal");
|
||||
```
|
||||
|
||||
Here's how we can represent `animal` object and `Animal` class graphically:
|
||||
|
||||

|
||||
|
||||
...And we would like to create another `class Rabbit`.
|
||||
|
||||
...And `Rabbit`:
|
||||
As rabbits are animals, `Rabbit` class should be based on `Animal`, have access to animal methods.
|
||||
|
||||
The syntax to extend another class is: `class Child extends Parent`.
|
||||
|
||||
Let's create `class Rabbit` that inherits from `Animal`:
|
||||
|
||||
```js
|
||||
class Rabbit {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
}
|
||||
hide() {
|
||||
alert(`${this.name} hides!`);
|
||||
}
|
||||
}
|
||||
|
||||
let rabbit = new Rabbit("My rabbit");
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
Right now they are fully independent.
|
||||
|
||||
But we'd want `Rabbit` to extend `Animal`. In other words, rabbits should be based on animals, have access to methods of `Animal` and extend them with its own methods.
|
||||
|
||||
To inherit from another class, we should specify `"extends"` and the parent class before the braces `{..}`.
|
||||
|
||||
Here `Rabbit` inherits from `Animal`:
|
||||
|
||||
```js run
|
||||
class Animal {
|
||||
constructor(name) {
|
||||
this.speed = 0;
|
||||
this.name = name;
|
||||
}
|
||||
run(speed) {
|
||||
this.speed += speed;
|
||||
alert(`${this.name} runs with speed ${this.speed}.`);
|
||||
}
|
||||
stop() {
|
||||
this.speed = 0;
|
||||
alert(`${this.name} stands still.`);
|
||||
}
|
||||
}
|
||||
|
||||
// Inherit from Animal by specifying "extends Animal"
|
||||
*!*
|
||||
class Rabbit extends Animal {
|
||||
*/!*
|
||||
|
@ -84,14 +55,12 @@ rabbit.run(5); // White Rabbit runs with speed 5.
|
|||
rabbit.hide(); // White Rabbit hides!
|
||||
```
|
||||
|
||||
Now the `Rabbit` code became a bit shorter, as it uses `Animal` constructor by default, and it also can `run`, as animals do.
|
||||
Object of `Rabbit` class have access to both `Rabbit` methods, such as `rabbit.hide()`, and also to `Animal` methods, such as `rabbit.run()`.
|
||||
|
||||
Internally, `extends` keyword adds `[[Prototype]]` reference from `Rabbit.prototype` to `Animal.prototype`:
|
||||
Internally, `extends` keyword works using the good old prototype mechanics. It sets `Rabbit.prototype.[[Prototype]]` to `Animal.prototype`. So, if a method is not found in `Rabbit.prototype`, JavaScript takes it from `Animal.prototype`.
|
||||
|
||||

|
||||
|
||||
So, if a method is not found in `Rabbit.prototype`, JavaScript takes it from `Animal.prototype`.
|
||||
|
||||
As we can recall from the chapter <info:native-prototypes>, JavaScript uses prototypal inheritance for build-in objects. E.g. `Date.prototype.[[Prototype]]` is `Object.prototype`, so dates have generic object methods.
|
||||
|
||||
````smart header="Any expression is allowed after `extends`"
|
||||
|
@ -119,19 +88,20 @@ That may be useful for advanced programming patterns when we use functions to ge
|
|||
|
||||
## Overriding a method
|
||||
|
||||
Now let's move forward and override a method. As of now, `Rabbit` inherits the `stop` method that sets `this.speed = 0` from `Animal`.
|
||||
Now let's move forward and override a method. By default, all methods that are not specified in `class Rabbit` are taken directly "as is" from `class Animal`.
|
||||
|
||||
If we specify our own `stop` in `Rabbit`, then it will be used instead:
|
||||
But if we specify our own method in `Rabbit`, such as `stop()` then it will be used instead:
|
||||
|
||||
```js
|
||||
class Rabbit extends Animal {
|
||||
stop() {
|
||||
// ...this will be used for rabbit.stop()
|
||||
// ...now this will be used for rabbit.stop()
|
||||
// instead of stop() from class Animal
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
...But usually we don't want to totally replace a parent method, but rather to build on top of it to tweak or extend its functionality. We do something in our method, but call the parent method before/after it or in the process.
|
||||
Usually we don't want to totally replace a parent method, but rather to build on top of it to tweak or extend its functionality. We do something in our method, but call the parent method before/after it or in the process.
|
||||
|
||||
Classes provide `"super"` keyword for that.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue