Skip to content

Commit 254bbf3

Browse files
authored
Merge pull request #586 from javascript-tutorial/joaquinelio-patch-1
class-inheritance updt
2 parents da9b38b + f4482e7 commit 254bbf3

File tree

2 files changed

+32
-32
lines changed

2 files changed

+32
-32
lines changed

1-js/09-classes/02-class-inheritance/2-clock-class-extended/task.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ importance: 5
44

55
# Reloj extendido
66

7-
Tenemos una clase de 'Clock'. A partir de ahora, imprime la hora cada segundo.
7+
Tenemos una clase 'Clock'. Por ahora, muestra la hora cada segundo.
88

99

1010
[js src="source.view/clock.js"]

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

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
# Herencia de clase
33

4-
La herencia de clase es un método para que una clase extienda a otra.
4+
La herencia de clase es el modo para que una clase extienda a otra.
55

6-
Entonces podemos crear una nueva funcionalidad además de la existente.
6+
De esta manera podemos añadir nueva funcionalidad a la ya existente.
77

88
## La palabra clave "extends"
99

@@ -34,9 +34,9 @@ Así es como podemos representar gráficamente el objeto `animal` y la clase `An
3434

3535
...Y nos gustaría crear otra clase `Rabbit`.
3636

37-
Como los conejos son animales, la clase 'Rabbit' debe basarse en 'Animal', tener acceso a métodos animales, para que los conejos puedan hacer lo que los animales "genéricos" pueden hacer.
37+
Como los conejos son animales, la clase 'Rabbit' debería basarse en 'Animal' y así tener acceso a métodos animales, para que los conejos puedan hacer lo que los animales "genéricos" pueden hacer.
3838

39-
La sintaxis para extender otra clase es: `class Child extends Parent`.
39+
La sintaxis para extender otra clase es: `class Hijo extends Padre`.
4040

4141
Construyamos la clase `Rabbit` que herede de `Animal`:
4242

@@ -61,12 +61,12 @@ Internamente, la palabra clave `extends` funciona con la buena mecánica de prot
6161

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

64-
Por ejemplo, para encontrar el método `rabbit.run`, el motor verifica (en la imagen, de abajo hacia arriba):
65-
1. El objeto `rabbit` (no tiene el método `run`).
66-
2. Su prototipo, que es `Rabbit.prototype` (tiene el método `hide`, pero no el método `run`).
67-
3. Su prototipo, que es `Animal.prototype` (debido a `extends`). Este finalmente tiene el método `run`.
64+
Por ejemplo, para encontrar el método `rabbit.run`, el motor revisa (en la imagen, de abajo hacia arriba):
65+
1. El objeto `rabbit`: no tiene el método `run`.
66+
2. Su prototipo, que es `Rabbit.prototype`: tiene el método `hide`, pero no el método `run`.
67+
3. Su prototipo, que es `Animal.prototype` (debido a `extends`): Este finalmente tiene el método `run`.
6868

69-
Como podemos recordar del capítulo <info:native-prototypes>, JavaScript usa la misma herencia prototípica para los objetos incorporados. Por ejemplo `Date.prototype.[[Prototype]]` es `Object.prototype`, por lo que "Date" tiene acceso a métodos de objeto genéricos.
69+
Como podemos recordar del capítulo <info:native-prototypes>, JavaScript usa la misma herencia prototípica para los objetos incorporados. Por ejemplo, `Date.prototype.[[Prototype]]` es `Object.prototype`. Es por esto que "Date" tiene acceso a métodos de objeto genéricos.
7070

7171
````smart header="Cualquier expresión está permitida después de `extends`"
7272
La sintaxis de clase permite especificar no solo una clase, sino cualquier expresión después de `extends`.
@@ -86,7 +86,7 @@ class User extends f("Hola") {}
8686

8787
new User().sayHi(); // Hola
8888
```
89-
Observa: `class User` hereda del resultado de `f("Hola")`.
89+
Observa que `class User` hereda del resultado de `f("Hola")`.
9090

9191
Eso puede ser útil para patrones de programación avanzados cuando usamos funciones para generar clases dependiendo de muchas condiciones y podamos heredar de ellas.
9292
````
@@ -95,7 +95,7 @@ Eso puede ser útil para patrones de programación avanzados cuando usamos funci
9595
9696
Ahora avancemos y sobrescribamos un método. Por defecto, todos los métodos que no están especificados en la clase `Rabbit` se toman directamente "tal cual" de la clase `Animal`.
9797
98-
Pero Si especificamos nuestro propio método `stop()` en `Rabbit`, este se utilizará en su lugar:
98+
Pero Si especificamos nuestro propio método `stop()` en `Rabbit`, es el que se utilizará en su lugar:
9999
100100
```js
101101
class Rabbit extends Animal {
@@ -106,11 +106,11 @@ class Rabbit extends Animal {
106106
}
107107
```
108108
109-
Usualmente no queremos reemplazar totalmente un método padre, sino más bien construir sobre él, modificar o ampliar su funcionalidad. Hacemos algo en nuestro método, pero llamamos al método padre antes, después o durante el proceso.
109+
Usualmente, no queremos reemplazar totalmente un método padre, sino más bien construir sobre él, modificarlo o ampliar su funcionalidad. Hacemos algo con nuestro método, pero queremos llamar al método padre antes, después o durante el proceso.
110110
111111
Las clases proporcionan la palabra clave `"super"` para eso.
112112
113-
- `super.method(...)` llama un método padre.
113+
- `super.metodo(...)` llama un método padre.
114114
- `super(...)` llama un constructor padre (solo dentro de nuestro constructor).
115115
116116
Por ejemplo, hagamos que nuestro conejo se oculte automáticamente cuando se detenga:
@@ -159,7 +159,7 @@ Ahora `Rabbit` tiene el método `stop` que llama al padre `super.stop()` en el p
159159
````smart header="Las funciones de flecha no tienen `super`"
160160
Como se mencionó en el capítulo <info:arrow-functions>, las funciones de flecha no tienen `super`.
161161
162-
Si se accede, se toma de la función externa. Por ejemplo:
162+
Si se lo accede, lo toma de la función externa. Por ejemplo:
163163
```js
164164
class Rabbit extends Animal {
165165
stop() {
@@ -168,7 +168,7 @@ class Rabbit extends Animal {
168168
}
169169
```
170170
171-
El método `super` en la función de flecha es el mismo que en `stop()`, y funciona según lo previsto. Si aquí especificamos una función "regular", habría un error:
171+
El método `super` en la función de flecha es el mismo que en `stop()`, y funciona según lo previsto. Si aquí especificáramos una función "regular", habría un error:
172172
173173
```js
174174
// super inesperado
@@ -187,7 +187,7 @@ De acuerdo con la [especificación](https://tc39.github.io/ecma262/#sec-runtime-
187187

188188
```js
189189
class Rabbit extends Animal {
190-
// generado para extender clases sin constructores propios
190+
// es generado por extender la clase sin constructor propio
191191
*!*
192192
constructor(...args) {
193193
super(...args);
@@ -196,7 +196,7 @@ class Rabbit extends Animal {
196196
}
197197
```
198198

199-
Como podemos ver, básicamente llama al padre `constructor` pasándole todos los argumentos. Eso sucede si no escribimos un constructor propio.
199+
Como podemos ver, básicamente llama al `constructor` padre pasándole todos los argumentos. Esto sucede si no escribimos un constructor propio.
200200

201201
Ahora agreguemos un constructor personalizado a `Rabbit`. Especificará `earLength` además de `name`:
202202

@@ -273,7 +273,7 @@ class Rabbit extends Animal {
273273
}
274274

275275
*!*
276-
// now fine
276+
// todo bien ahora
277277
let rabbit = new Rabbit("Conejo Blanco", 10);
278278
alert(rabbit.name); // Conejo Blanco
279279
alert(rabbit.earLength); // 10
@@ -323,11 +323,11 @@ Aquí, la clase `Rabbit` extiende `Animal` y sobrescribe el campo `name` con un
323323

324324
Lo interesante es que en ambos casos: `new Animal()` y `new Rabbit()`, el `alert` en la línea `(*)` muestra `animal`.
325325

326-
**En otras palabras, el constructor padre siempre usa el valor de su propios campo de clase, no el sobrescrito.**
326+
**En otras palabras, el constructor padre siempre usa el valor de su propio campo de clase, no el sobrescrito.**
327327

328328
¿Qué es lo extraño de esto?
329329

330-
Si esto aún no está claro, compara con métodos.
330+
Si esto aún no está claro, compara lo que ocurre con los métodos.
331331

332332
Aquí está el mismo código, pero en lugar del campo `this.name` llamamos el método `this.showName()`:
333333

@@ -368,11 +368,11 @@ Bien, la razón está en el orden de inicialización, El campo de clase es inici
368368

369369
En nuestro caso, `Rabbit` es la clase derivada. No hay `constructor()` en ella. Como establecimos previamente, es lo mismo que si hubiera un constructor vacío con solamente `super(...args)`.
370370

371-
Entonces, `new Rabbit()` llama a `super()` y se ejecuta el constructor padre, y (por la regla de la clase derivada) solamente después de que sus campos de clase sean inicializados. En el momento de la ejecución del constructor padre, todavía no existen los campos de clase de `Rabbit`, por ello los campos de `Animal` son los usado.
371+
Entonces, `new Rabbit()` llama a `super()` y se ejecuta el constructor padre, y (por la regla de la clase derivada) solamente después de que sus campos de clase sean inicializados. En el momento de la ejecución del constructor padre, todavía no existen los campos de clase de `Rabbit`, por ello los campos de `Animal` son los usados.
372372

373373
Esta sutil diferencia entre campos y métodos es particular de JavaScript
374374

375-
Afortunadamente este comportamiento solo se revela si los campos sobrescritos son usados en el constructor padre. Entonces puede ser difícil entender qué es lo que está pasando, por ello lo explicamos aquí.
375+
Afortunadamente este comportamiento solo se revela si los campos sobrescritos son usados en el constructor padre. En tal caso puede ser difícil entender qué es lo que está pasando, por ello lo explicamos aquí.
376376

377377
Si esto e vuelve un problema, uno puede corregirlo usando métodos o getters/setters en lugar de campos.
378378

@@ -389,9 +389,9 @@ Vamos a profundizar un poco más el tema de `super`. Veremos algunas cosas inter
389389

390390
En primer lugar, de todo lo que hemos aprendido hasta ahora, ¡es imposible que `super` funcione en absoluto!
391391

392-
Sí, de hecho, preguntémonos, ¿cómo debería funcionar técnicamente? Cuando se ejecuta un método de objeto, obtiene el objeto actual como `this`. Si llamamos a `super.method()` entonces, el motor necesita obtener el `method` del prototipo del objeto actual. ¿Pero cómo?
392+
Entonces, preguntémonos: ¿cómo debería funcionar técnicamente? Cuando se ejecuta un método de objeto, obtiene el objeto actual como `this`. Si llamamos a `super.method()` entonces, el motor necesita obtener el `method` del prototipo del objeto actual. ¿Pero cómo?
393393

394-
La tarea puede parecer simple, pero no lo es. El motor conoce el objeto actual `this`, por lo que podría obtener el `method` padre como `this.__proto __.method`. Desafortunadamente, una solución tan "ingenua" no funcionará.
394+
La tarea puede parecer simple, pero no lo es. El motor conoce el objeto actual `this`, por lo que podría obtener el `method` padre como `this.__proto __.method`. Desafortunadamente, una solución tan "ingenua" no funcionará.
395395

396396
Demostremos el problema. Sin clases, usando objetos puros por simplicidad.
397397

@@ -475,7 +475,7 @@ Aquí está la imagen de lo que sucede:
475475
// es decir
476476
rabbit.eat.call(this);
477477
```
478-
2. Luego, en la línea `(*)` de `rabbit.eat`, nos gustaría pasar la llamada aún más arriba en la cadena, evitando `this=longEar`, entonces `this.__ proto__.eat` es nuevamente `rabbit.eat`!
478+
2. Luego, en la línea `(*)` de `rabbit.eat`, queremos pasar la llamada aún más arriba en la cadena; pero como `this=longEar`, entonces `this.__ proto__.eat` ¡es nuevamente `rabbit.eat`!
479479

480480
```js
481481
// dentro de rabbit.eat () también tenemos this = longEar
@@ -488,7 +488,7 @@ Aquí está la imagen de lo que sucede:
488488

489489
3. ...Entonces `rabbit.eat` se llama a sí mismo en el bucle sin fin, porque no puede ascender más.
490490

491-
El problema no se puede resolver usando solo `this`.
491+
El problema no se puede resolver usando solamente `this`.
492492

493493
### `[[HomeObject]]`
494494

@@ -534,7 +534,7 @@ Funciona según lo previsto, debido a la mecánica de `[[HomeObject]]`. Un méto
534534

535535
### Los métodos no son "libres"
536536

537-
Como hemos sabido antes, generalmente las funciones son "libres", es decir no están vinculadas a objetos en JavaScript. Para que puedan copiarse entre objetos y llamarse con otro 'this`.
537+
Como aprendimos antes, generalmente las funciones son "libres", es decir que no están vinculadas a objetos en JavaScript. Esto es para que puedan copiarse entre objetos y llamarse con otro 'this`.
538538
539539
La existencia misma de `[[HomeObject]]` viola ese principio, porque los métodos recuerdan sus objetos. `[[HomeObject]]` no se puede cambiar, por lo que este vínculo es para siempre.
540540
@@ -616,12 +616,12 @@ rabbit.eat(); // Error al llamar a super (porque no hay [[HomeObject]])
616616
617617
## Resumen
618618
619-
1. Para extender una clase: `class Child extends Parent`:
620-
     - Eso significa que `Child.prototype.__proto__` será `Parent.prototype`, por lo que los métodos se heredan.
619+
1. Para extender una clase: `class Hijo extends Padre`:
620+
     - Eso significa que `Hijo.prototype.__proto__` será `Padre.prototype`, por lo que los métodos se heredan.
621621
2. Al sobrescribir un constructor:
622-
     - Debemos llamar al constructor padre como `super()` en el constructor `Child` antes de usar `this`.
622+
     - Debemos llamar al constructor del padre `super()` en el constructor de `Hijo` antes de usar `this`.
623623
3. Al sobrescribir otro método:
624-
     - Podemos usar `super.method()` en un método `Child` para llamar al método `Parent`.
624+
     - Podemos usar `super.method()` en un método `Hijo` para llamar al método `Padre`.
625625
4. Características internas:
626626
     - Los métodos recuerdan su clase/objeto en la propiedad interna `[[HomeObject]]`. Así es como `super` resuelve los métodos padres.
627627
     - Por lo tanto, no es seguro copiar un método con `super` de un objeto a otro.

0 commit comments

Comments
 (0)