Skip to content

Commit 635589f

Browse files
authored
👾 smth
1 parent cde307b commit 635589f

1 file changed

Lines changed: 62 additions & 10 deletions

File tree

1-js/09-classes/02-class-inheritance/article.md

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
12
# Наследование классов
23

3-
Допустим, у нас есть два класса.
4+
Наследование классов - это возможность для одного класса расширить другой класс.
5+
6+
Таким образом, мы можем создавать новые функциональные возможности поверх существующих.
7+
8+
## Ключевое слово "extends"
49

5-
`Animal`:
10+
Допустим, у нас есть класс `Animal`:
611

712
```js
813
class Animal {
@@ -16,31 +21,78 @@ class Animal {
1621
}
1722
stop() {
1823
this.speed = 0;
19-
alert(`${this.name} стоит.`);
24+
alert(`${this.name} стоит неподвижно.`);
2025
}
2126
}
2227

2328
let animal = new Animal("Мой питомец");
2429
```
2530

31+
Вот как мы можем представить объект `animal` и класс `Animal` графически:
32+
2633
![](rabbit-animal-independent-animal.svg)
2734

28-
...И `Rabbit`:
35+
...И мы хотели бы создать еще один `class Rabbit`.
36+
37+
Поскольку кролики - это животные, класс `Rabbit` должен быть основан на `Animal`, иметь доступ к методам animal, так чтобы кролики могли делать то, что могут делать "общие" животные.
38+
39+
Синтаксис для расширения другого класса таков: `class Child extends Parent`.
40+
41+
Давайте создадим класс `Rabbit`, который наследуется от `Animal`:
2942

3043
```js
31-
class Rabbit {
32-
constructor(name) {
33-
this.name = name;
34-
}
44+
*!*
45+
class Rabbit extends Animal {
46+
*/!*
3547
hide() {
3648
alert(`${this.name} прячется!`);
3749
}
3850
}
3951

40-
let rabbit = new Rabbit("Мой кролик");
52+
let rabbit = new Rabbit("Белый кролик");
53+
54+
rabbit.run(5); // Белый кролик бежит со скоростью 5.
55+
rabbit.hide(); // Белый кролик прячется!
56+
```
57+
58+
Объект класса `Rabbit` имеет доступ как к методам `Rabbit`, таким как `rabbit.hide()`, так и к методам `Animal`, таким как `rabbit.run()`.
59+
60+
Внутренне ключевое слово `extends` работает с использованием старой доброй механики прототипов. Он устанавливает `Rabbit.prototype.[[Prototype]]` на `Animal.prototype`. Таким образом, если метод не был найден в `Rabbit.prototype`, JavaScript берет его из `Animal.prototype`.
61+
62+
![](animal-rabbit-extends.svg)
63+
64+
Например, чтобы найти метод `rabbit.run`, движок проверяет (снизу вверх на картинке):
65+
1. Объект `rabbit` (не имеет `run`).
66+
2. Его прототип, то есть `Rabbit.prototype` (имеет `hide`, но не `run`).
67+
3. Его прототип, то есть (вследствие `extends`) `Animal.prototype`, в котором, наконец, есть метод `run`.
68+
69+
Как мы помним из главы <info:native-prototypes>, в JavaScript используется наследование на прототипах для встроенных объектов. Например `Date.prototype.[[Prototype]]` это `Object.prototype`. Вот почему у dates есть доступ к общим объектным методам.
70+
71+
````smart header="Any expression is allowed after `extends`"
72+
Class syntax allows to specify not just a class, but any expression after `extends`.
73+
74+
For instance, a function call that generates the parent class:
75+
76+
```js run
77+
function f(phrase) {
78+
return class {
79+
sayHi() { alert(phrase); }
80+
};
81+
}
82+
83+
*!*
84+
class User extends f("Hello") {}
85+
*/!*
86+
87+
new User().sayHi(); // Hello
4188
```
89+
Here `class User` inherits from the result of `f("Hello")`.
90+
91+
That may be useful for advanced programming patterns when we use functions to generate classes depending on many conditions and can inherit from them.
92+
````
93+
94+
4295
43-
![](rabbit-animal-independent-rabbit.svg)
4496
4597
Сейчас они полностью независимы.
4698

0 commit comments

Comments
 (0)