Skip to content

Commit 3620843

Browse files
Apply fixes and translate untranslated sentences in '1-js/09-classes/02-class-inheritance/article.md'
1 parent 88d661f commit 3620843

File tree

1 file changed

+54
-50
lines changed

1 file changed

+54
-50
lines changed

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

Lines changed: 54 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
L'héritage de classe est un moyen pour une classe d'étendre une autre classe.
55

6-
So we can create new functionality on top of the existing.
6+
Nous pouvons donc créer de nouvelles fonctionnalités à partir de celles qui existent déjà.
77

8-
## The "extends" keyword
8+
## Le mot-clé "extends"
99

10-
Let's say we have class `Animal`:
10+
Supposons que nous ayons la classe `Animal` :
1111

1212
```js
1313
class Animal {
@@ -38,7 +38,7 @@ Comme les lapins sont des animaux, la classe `Rabbit` devrait être basé sur `A
3838

3939
La syntaxe pour étendre une autre classe est la suivante : `class Child extends Parent`.
4040

41-
Let's create `class Rabbit` that inherits from `Animal`:
41+
Créons `class Rabbit` qui hérite de `Animal` :
4242

4343
```js
4444
*!*
@@ -55,13 +55,14 @@ rabbit.run(5); // White Rabbit court à la vitesse 5.
5555
rabbit.hide(); // White Rabbit se cache!
5656
```
5757

58-
L’objet de la classe `Rabbit` a accès aux deux méthodes `Rabbit`, telles que `rabbit.hide()`, ainsi qu'aux méthodes `Animal`, telles que `rabbit.run()`.
58+
L’objet de la classe `Rabbit` a accès à la fois aux méthodes `Rabbit`, telles que `rabbit.hide()`, et aux méthodes `Animal`, telles que `rabbit.run()`.
5959

6060
En interne, le mot clé `extended` fonctionne en utilisant le bon vieux prototype. Il établit `Rabbit.prototype.[[Prototype]]` vers `Animal.prototype`. Donc, si une méthode n'est pas trouvée dans `Rabbit.prototype`, JavaScript le prend de `Animal.prototype`.
6161

6262
![](animal-rabbit-extends.svg)
6363

6464
Par exemple, pour trouver la méthode `rabbit.run`, le moteur vérifie (de bas en haut sur l'image) :
65+
6566
1. L'objet `rabbit` (n'a pas de `run`).
6667
2. Son prototype, c'est-à-dire `Rabbit.prototype` (a `hide`, mais pas `run`).
6768
3. Son prototype, c'est-à-dire (en raison de `extends`) `Animal.prototype`, qui a finalement la méthode `run`.
@@ -71,7 +72,7 @@ Comme nous pouvons nous en rappeler dans le chapitre <info:native-prototypes>, J
7172
````smart header="Toute expression est autorisée après `extend`"
7273
La syntaxe de classe permet de spécifier non seulement une classe, mais toute expression après `extend`.
7374

74-
Par exemple, un appel de fonction qui génère la classe parent:
75+
Par exemple, un appel de fonction qui génère la classe parent :
7576

7677
```js run
7778
function f(phrase) {
@@ -100,8 +101,8 @@ Mais si nous spécifions notre propre méthode dans `Rabbit`, telle que `stop()`
100101
```js
101102
class Rabbit extends Animal {
102103
stop() {
103-
// ...now this will be used for rabbit.stop()
104-
// instead of stop() from class Animal
104+
// ...maintenant ceci sera utilisé pour rabbit.stop()
105+
// au lieu de stop() de la classe Animal
105106
}
106107
}
107108
```
@@ -113,7 +114,7 @@ Les classes fournissent le mot clé `"super"` pour cela.
113114
- `super.method(...)` pour appeler une méthode parente.
114115
- `super(...)` pour appeler un constructeur parent (dans notre constructeur uniquement).
115116
116-
Par exemple, laisson rabbit se cacher automatiquement à l’arrêt:
117+
Par exemple, laisson rabbit se cacher automatiquement à l’arrêt :
117118
118119
```js run
119120
class Animal {
@@ -157,9 +158,9 @@ rabbit.stop(); // White Rabbit reste immobile. White Rabbit se cache!
157158
Maintenant, `Rabbit` a la méthode `stop` qui appelle le `super.stop()` du parent dans le processus.
158159
159160
````smart header="Les fonctions fléchées n'ont pas de `super`"
160-
Comme mentionné dans le chapitre <info: arrow-functions>, les fonctions fléchées n'ont pas `super`.
161+
Comme mentionné dans le chapitre <info:arrow-functions>, les fonctions fléchées n'ont pas `super`.
161162
162-
Si on y accède, c'est tiré de la fonction externe. Par exemple:
163+
Si on y accède, c'est tiré de la fonction externe. Par exemple :
163164
164165
```js
165166
class Rabbit extends Animal {
@@ -169,7 +170,7 @@ class Rabbit extends Animal {
169170
}
170171
```
171172
172-
Le `super` dans la fonction fléchée est le même que dans `stop()`, donc cela fonctionne comme prévu. Si nous spécifions ici une fonction "régulière", il y aurait une erreur:
173+
Le `super` dans la fonction fléchée est le même que dans `stop()`, donc cela fonctionne comme prévu. Si nous spécifions ici une fonction "régulière", il y aurait une erreur :
173174
174175
```js
175176
// Super inattendu
@@ -183,11 +184,11 @@ Avec les constructeurs, cela devient un peu délicat.
183184

184185
Jusqu'à maintenant, `Rabbit` n'avait pas son propre `constructor`.
185186

186-
Selon la [spécification](https://tc39.github.io/ecma262/#sec-runtime-semantics-classdefinitionevaluation), si une classe étend une autre classe et n'a pas de 'constructeur', alors le `constructor` "vide" suivant est généré:
187+
Selon la [spécification](https://tc39.github.io/ecma262/#sec-runtime-semantics-classdefinitionevaluation), si une classe étend une autre classe et n'a pas de `constructor`, alors le `constructor` "vide" suivant est généré :
187188

188189
```js
189190
class Rabbit extends Animal {
190-
// généré pour l'extension de classes sans propres constructeurs
191+
// généré pour l'extension de classes sans constructeur propre
191192
*!*
192193
constructor(...args) {
193194
super(...args);
@@ -198,7 +199,7 @@ class Rabbit extends Animal {
198199

199200
Comme nous pouvons le constater, il appelle essentiellement le `constructor` du parent en lui passant tous les arguments. Cela se produit si nous n'écrivons pas notre propre constructeur.
200201

201-
Ajoutons maintenant un constructeur personnalisé à `Rabbit`. Il spécifiera le `earLength` en plus de `name`:
202+
Ajoutons maintenant un constructeur personnalisé à `Rabbit`. Il spécifiera le `earLength` en plus de `name` :
202203

203204
```js run
204205
class Animal {
@@ -228,13 +229,13 @@ let rabbit = new Rabbit("White Rabbit", 10); // Error: this is not defined.
228229
*/!*
229230
```
230231

231-
Oups! Nous avons une erreur. Maintenant, nous ne pouvons pas créer de lapins. Qu'est-ce qui s'est passé?
232+
Oups ! Nous avons une erreur. Maintenant, nous ne pouvons pas créer de lapins. Qu'est-ce qui s'est passé ?
232233

233-
La réponse courte est :
234+
La réponse courte est :
234235

235236
- **les constructeurs dans les classes qui héritent doivent appeler `super(...)`, et (!) le faire avant d'utiliser `this`.**
236237

237-
...Mais pourquoi? Que se passe t-il ici? En effet, l'exigence semble étrange.
238+
...Mais pourquoi ? Que se passe t-il ici ? En effet, l'exigence semble étrange.
238239

239240
Bien sûr, il y a une explication. Entrons dans les détails pour que vous compreniez vraiment ce qui se passe.
240241

@@ -245,7 +246,7 @@ Ce label affecte son comportement avec `new`.
245246
- Lorsqu'une fonction normale est exécutée avec `new`, elle crée un objet vide et l'assigne à `this`.
246247
- Mais lorsqu'un constructeur dérivé s'exécute, il ne le fait pas. Il s'attend à ce que le constructeur parent fasse ce travail.
247248

248-
Ainsi, un constructeur dérivé doit appeler `super` pour exécuter son constructeur parent (de base), sinon l'objet pour` this` ne sera pas créé. Et nous aurons une erreur.
249+
Ainsi, un constructeur dérivé doit appeler `super` pour exécuter son constructeur parent (de base), sinon l'objet pour `this` ne sera pas créé. Et nous aurons une erreur.
249250

250251
Pour que le constructeur `Rabbit` fonctionne, il doit appeler `super()` avant d'utiliser `this`, comme ici :
251252

@@ -273,14 +274,13 @@ class Rabbit extends Animal {
273274
}
274275

275276
*!*
276-
// now fine
277+
// maintenant ça marche
277278
let rabbit = new Rabbit("White Rabbit", 10);
278279
alert(rabbit.name); // White Rabbit
279280
alert(rabbit.earLength); // 10
280281
*/!*
281282
```
282283

283-
284284
### Remplacer les champs de classe : une note délicate
285285

286286
```warn header="Note avancée"
@@ -328,7 +328,7 @@ Qu'est-ce qui est étrange à ce sujet ?
328328

329329
Si ce n'est pas encore clair, veuillez comparer avec les méthodes.
330330

331-
Voici le même code, mais au lieu du champ `this.name`, nous appelons la méthode `this.showName()`:
331+
Voici le même code, mais au lieu du champ `this.name`, nous appelons la méthode `this.showName()` :
332332

333333
```js run
334334
class Animal {
@@ -353,29 +353,29 @@ new Rabbit(); // rabbit
353353
*/!*
354354
```
355355

356-
Remarque: maintenant la sortie est différente.
356+
Remarque : maintenant la sortie est différente.
357357

358358
Et c'est ce à quoi nous nous attendons naturellement. Lorsque le constructeur parent est appelé dans la classe dérivée, il utilise la méthode substituée.
359359

360-
... Mais ce n'est pas le cas pour les champs de classe. Comme dit, le constructeur parent utilise toujours le champ parent.
360+
... Mais ce n'est pas le cas pour les champs de classe. Comme nous l'avons dit, le constructeur parent utilise toujours le champ parent.
361361

362362
Pourquoi y a-t-il une différence ?
363363

364364
Eh bien, la raison est dans l'ordre d'initialisation du champ. Le champ de classe est initialisé :
365+
365366
- Avant le constructeur de la classe de base (qui n'étend rien),
366367
- Immédiatement après `super()` pour la classe dérivée.
367368

368369
Dans notre cas, `Rabbit` est la classe dérivée. Il n'y a pas de `constructor()` dedans. Comme dit précédemment, c'est la même chose que s'il y avait un constructeur vide avec seulement `super(...args)`.
369370

370-
Ainsi, `new Rabbit()` appelle `super()`, exécutant ainsi le constructeur parent, et (selon la règle pour les classes dérivées) seulement après que ses champs de classe sont initialisés. Au moment de l'exécution du constructeur parent, il n'y a pas encore de champs de classe `Rabbit`, c'est pourquoi les champs `Animal` sont utilisés.
371+
Ainsi, `new Rabbit()` appelle `super()`, exécutant ainsi le constructeur parent, et (selon la règle pour les classes dérivées) seulement après cela ses champs de classe sont initialisés. Au moment de l'exécution du constructeur parent, il n'y a pas encore de champs de classe `Rabbit`, c'est pourquoi les champs `Animal` sont utilisés.
371372

372373
Cette subtile différence entre les champs et les méthodes est propre à JavaScript.
373374

374375
Heureusement, ce comportement ne se révèle que si un champ surchargé est utilisé dans le constructeur parent. Ensuite, il peut être difficile de comprendre ce qui se passe, alors nous l'expliquons ici.
375376

376377
Si cela devient un problème, on peut le résoudre en utilisant des méthodes ou des getters / setters au lieu de champs.
377378

378-
379379
## Super: les internes, [[HomeObject]]
380380

381381
```warn header="Informations avancées"
@@ -386,17 +386,17 @@ Il concerne les mécanismes internes de l'héritage et du "super".
386386

387387
Poussons un peu plus loin sous le capot de `super`. Nous y verrons des choses intéressantes.
388388

389-
Tout d'abord, d'après tout ce que nous avons appris jusqu'à présent, `super` ne devrait pas fonctionner du tout!
389+
Tout d'abord, d'après tout ce que nous avons appris jusqu'à présent, `super` ne devrait pas fonctionner du tout !
390390

391-
Oui, en effet, demandons-nous comment cela devrait fonctionner techniquement? Lorsqu'une méthode d'objet est exécutée, l'objet actuel est remplacé par `this`. Si nous appelons `super.method()`, le moteur doit obtenir la `méthode` à partir du prototype de l'objet actuel. Mais comment?
391+
Oui, en effet, demandons-nous comment cela devrait fonctionner techniquement ? Lorsqu'une méthode d'objet est exécutée, l'objet actuel est remplacé par `this`. Si nous appelons `super.method()`, le moteur doit obtenir la `methode` à partir du prototype de l'objet actuel. Mais comment ?
392392

393-
La tâche peut sembler simple, mais elle ne l’est pas. Le moteur connaît l'objet en cours `this`, de sorte qu'il pourrait obtenir la méthode `méthode` parent sous la forme `this.__proto__.Method`. Malheureusement, une telle solution "naïve" ne fonctionnera pas.
393+
La tâche peut sembler simple, mais elle ne l’est pas. Le moteur connaît l'objet en cours `this`, de sorte qu'il pourrait obtenir la `methode` parent sous la forme `this.__proto__.Method`. Malheureusement, une telle solution "naïve" ne fonctionnera pas.
394394

395395
Montrons le problème. Sans les classes, en utilisant des objets simples pour des raisons de simplicité.
396396

397397
Si vous ne voulez pas connaître les détails, vous pouvez sauter cette partie et aller en bas à la sous-section `[[HomeObject]]`. Cela ne fera pas de mal. Ou lisez si vous souhaitez comprendre les choses en profondeur.
398398

399-
Dans l'exemple ci-dessous, `rabbit.__proto__=animal`. Essayons maintenant: dans `rabbit.eat()` nous appellerons `animal.eat()`, en utilisant `this.__proto__`:
399+
Dans l'exemple ci-dessous, `rabbit.__proto__=animal`. Essayons maintenant : dans `rabbit.eat()` nous appellerons `animal.eat()`, en utilisant `this.__proto__` :
400400

401401
```js run
402402
let animal = {
@@ -420,11 +420,11 @@ let rabbit = {
420420
rabbit.eat(); // Rabbit eats.
421421
```
422422

423-
À la ligne `(*)` nous prenons `eat` du prototype (`animal`) et l'appelons dans le contexte de l'objet actuel. Veuillez noter que `.call(this)` est important ici, car un simple `this.__proto__.Eat()` exécuterait le `eat` du parent dans le contexte du prototype et non de l'objet actuel.
423+
À la ligne `(*)` nous prenons `eat` du prototype (`animal`) et l'appelons dans le contexte de l'objet actuel. Veuillez noter que `.call(this)` est important ici, car un simple `this.__proto__.eat()` exécuterait le `eat` du parent dans le contexte du prototype et non de l'objet actuel.
424424

425-
Et dans le code ci-dessus, cela fonctionne réellement comme prévu: nous avons la bonne `alert`.
425+
Et dans le code ci-dessus, cela fonctionne réellement comme prévu : nous avons la bonne `alert`.
426426

427-
Ajoutons maintenant un objet de plus à la chaîne. Nous verrons comment les choses se casse:
427+
Ajoutons maintenant un objet de plus à la chaîne. Nous verrons comment les choses se cassent :
428428

429429
```js run
430430
let animal = {
@@ -455,17 +455,18 @@ longEar.eat(); // Error: Maximum call stack size exceeded
455455
*/!*
456456
```
457457

458-
Le code ne fonctionne plus! Nous pouvons voir l'erreur en essayant d'appeler `longEar.eat()`.
458+
Le code ne fonctionne plus ! Nous pouvons voir l'erreur en essayant d'appeler `longEar.eat()`.
459459

460-
Ce n'est peut-être pas si évident, mais si nous suivons l'appel de `longEar.eat()`, nous pouvons voir pourquoi. Dans les deux lignes `(*)` et `(**)`, la valeur de `this` est l'objet actuel (`longEar`). C'est essentiel: toutes les méthodes d'objet obtiennent l'objet actuel sous la forme `this`, pas un prototype ou quelque chose d'autre.
460+
Ce n'est peut-être pas si évident, mais si nous suivons l'appel de `longEar.eat()`, nous pouvons voir pourquoi. Dans les deux lignes `(*)` et `(**)`, la valeur de `this` est l'objet actuel (`longEar`). C'est essentiel : toutes les méthodes d'objet obtiennent l'objet actuel sous la forme `this`, pas un prototype ou quelque chose d'autre.
461461

462-
Ainsi, dans les deux lignes `(*)` et `(**)`, la valeur de `this.__proto__` est exactement la même: `rabbit`. Ils appellent tous deux `rabbit.eat` sans remonter la chaîne, dans une boucle infinie.
462+
Ainsi, dans les deux lignes `(*)` et `(**)`, la valeur de `this.__proto__` est exactement la même : `rabbit`. Ils appellent tous deux `rabbit.eat` sans remonter la chaîne, dans une boucle infinie.
463463

464-
Voici l'image de ce qui se passe:
464+
Voici l'image de ce qui se passe :
465465

466466
![](this-super-loop.svg)
467467

468468
1. Dans `longEar.eat()`, la ligne `(**)` appelle `rabbit.eat` et lui fournit `this = longEar`.
469+
469470
```js
470471
// dans longEar.eat() nous avons this = longEar
471472
this.__proto__.eat.call(this) // (**)
@@ -474,7 +475,8 @@ Voici l'image de ce qui se passe:
474475
// à savoir
475476
rabbit.eat.call(this);
476477
```
477-
2. Ensuite, dans la ligne `(*)` de `rabbit.eat`, nous aimerions passer l'appel encore plus haut dans la chaîne, mais `this = longEar`, donc `this.__proto__.eat` est encore `rabbit.eat`!
478+
479+
2. Ensuite, dans la ligne `(*)` de `rabbit.eat`, nous aimerions passer l'appel encore plus haut dans la chaîne, mais `this = longEar`, donc `this.__proto__.eat` est encore `rabbit.eat` !
478480
479481
```js
480482
// dans rabbit.eat() nous avons aussi this = longEar
@@ -491,13 +493,13 @@ Le problème ne peut pas être résolu en utilisant seulement `this`.
491493
492494
### `[[HomeObject]]`
493495
494-
Pour fournir la solution, JavaScript ajoute une propriété interne spéciale supplémentaire pour les fonctions: `[[HomeObject]]`.
496+
Pour fournir la solution, JavaScript ajoute une propriété interne spéciale supplémentaire pour les fonctions : `[[HomeObject]]`.
495497
496498
Lorsqu'une fonction est spécifiée en tant que méthode de classe ou d'objet, sa propriété `[[HomeObject]]` devient cet objet.
497499
498500
Ensuite, `super` l'utilise pour résoudre le prototype parent et ses méthodes.
499501

500-
Voyons comment cela fonctionne, d'abord avec les objets simples:
502+
Voyons comment cela fonctionne, d'abord avec les objets simples :
501503
502504
```js run
503505
let animal = {
@@ -537,9 +539,9 @@ Comme nous l'avons vu précédemment, les fonctions sont généralement "libres"
537539

538540
L'existence même de `[[HomeObject]]` viole ce principe, car les méthodes se souviennent de leurs objets. `[[HomeObject]]` ne peut pas être changé, ce lien est donc permanent.
539541
540-
Le seul endroit dans la langue où `[[HomeObject]]` est utilisé - est `super`. Donc, si une méthode n'utilise pas `super`, on peut toujours la considérer comme libre et la copier entre les objets. Mais avec `super`, les choses peuvent mal tourner.
542+
Le seul endroit dans le langage où `[[HomeObject]]` est utilisé est `super`. Donc, si une méthode n'utilise pas `super`, on peut toujours la considérer comme libre et la copier entre les objets. Mais avec `super`, les choses peuvent mal tourner.
541543

542-
Voici la démo d'un mauvais résultat de `super` après la copie:
544+
Voici la démo d'un mauvais résultat de `super` après la copie :
543545
544546
```js run
545547
let animal = {
@@ -577,12 +579,13 @@ tree.sayHi(); // I'm an animal (?!?)
577579

578580
Un appel à `tree.sayHi()` indique "I'm an animal". Certainement faux.
579581

580-
La raison est simple:
581-
- Dans la ligne `(*)`, la méthode `tree.sayHi` a été copiée à partir de `rabbit`. Peut-être que nous voulions simplement éviter la duplication de code?
582+
La raison est simple :
583+
584+
- Dans la ligne `(*)`, la méthode `tree.sayHi` a été copiée à partir de `rabbit`. Peut-être que nous voulions simplement éviter la duplication de code ?
582585
- Son `[[[HomeObject]]` est `rabbit`, comme il a été créé dans `rabbit`. Il n'y a aucun moyen de changer `[[HomeObject]]`.
583586
- Le code de `tree.sayHi()` a `super.sayHi()` à l'intérieur. Il monte de `rabbit` et prend la méthode de `animal`.
584587

585-
Voici le schéma de ce qui se passe:
588+
Voici le schéma de ce qui se passe :
586589

587590
![](super-homeobject-wrong.svg)
588591

@@ -592,7 +595,7 @@ Voici le schéma de ce qui se passe:
592595

593596
La différence peut être non essentielle pour nous, mais c'est important pour JavaScript.
594597
595-
Dans l'exemple ci-dessous, une syntaxe non-méthode est utilisée pour la comparaison. La propriété `[[HomeObject]]` n'est pas définie et l'héritage ne fonctionne pas:
598+
Dans l'exemple ci-dessous, une syntaxe non-méthode est utilisée pour la comparaison. La propriété `[[HomeObject]]` n'est pas définie et l'héritage ne fonctionne pas :
596599

597600
```js run
598601
let animal = {
@@ -615,15 +618,16 @@ rabbit.eat(); // Error calling super (parce qu'il n'y a pas de [[HomeObject]])
615618

616619
## Résumé
617620

618-
1. Pour étendre une classe: `class Child extends Parent`:
621+
1. Pour étendre une classe : `class Child extends Parent` :
619622
- Cela signifie que `Child.prototype.__proto__` sera `Parent.prototype`, donc les méthodes sont héritées.
620-
2. Lors du remplacement d'un constructeur:
623+
2. Lors du remplacement d'un constructeur :
621624
- Nous devons appeler le constructeur parent en tant que `super()` dans le constructeur `Child` avant d'utiliser `this`.
622-
3. Lors du remplacement d'une autre méthode:
625+
3. Lors du remplacement d'une autre méthode :
623626
- Nous pouvons utiliser `super.method()` dans une méthode `Child` pour appeler la méthode `Parent`.
624-
4. Internes:
627+
4. Internes :
625628
- Les méthodes se souviennent de leur classe/objet dans la propriété interne `[[HomeObject]]`. C'est ainsi que `super` résout les méthodes parent.
626629
- Il n'est donc pas prudent de copier une méthode avec `super` d'un objet à un autre.
627630

628631
Également :
632+
629633
- Les fonctions fléchées n'ont pas leurs propre `this` ou `super`, elles s'adaptent donc de manière transparente au contexte environnant.

0 commit comments

Comments
 (0)