Skip to content

13. Clases

Image

Aquí introducimos las clases de ECMAScript 6. En primer lugar, mostramos que las funciones ya se pueden utilizar como clases.

13.1. script [class-00]

El siguiente script demuestra un uso inusual de las funciones. Aquí, se utilizan como objetos.


1. 'use strict';
2. // a function can be used as an object
3. 
4. // an empty shell
5. function f() {
6. 
7. }
8. // to which properties are assigned from the outside
9. f.prop1 = "val1";
10. f.show = function () {
11.   console.log(this.prop1);
12. }
13. // using f
14. f.show();
15. 
16. // a function g acting as a class
17. function g() {
18.   this.prop2 = "val2";
19.   this.show = function () {
20.     console.log(this.prop2);
21.   }
22. }
23. // Instantiate the function with [new]
24. new g().show();

Comentarios

  • líneas 5-7: el cuerpo de la función f no define ninguna propiedad;
  • líneas 9-12: se asignan propiedades a la función f desde fuera;
  • línea 14: uso de la función (objeto) f. Observa que no escribimos [f()] sino simplemente [f]. Esta es la notación para un objeto;
  • líneas 17-22: definimos una función [g] como si fuera una clase con propiedades y métodos;
  • línea 24: la función [g] es instanciada por [new g()];

Resultados de la ejecución


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-00.js"
2. val1
3. val2

ES6 introdujo el concepto de clases, que ahora nos permite evitar el uso de funciones para crear clases.

13.2. script [class-01]

El [class-01] script presenta una [Persona] class:


1. // class
2. class Person {
3. 
4.   // constructor
5.   constructor(lastName, firstName, age) {
6.     this.lastName = lastName;
7.     this.firstName = firstName;
8.     this.age = age;
9.   }
10. 
11.   // getters and setters
12.   get name() {
13.     return this._name;
14.   }
15.   set name(value) {
16.     this._name = value;
17.   }
18. 
19.   get firstName() {
20.     return this._first_name;
21.   }
22.   set firstName(value) {
23.     this._first_name = value;
24.   }
25. 
26.   get age() {
27.     return this._age;
28.   }
29.   set age(value) {
30.     this._age = value;
31.   }
32. 
33.   // toString as JSON
34.   toString() {
35.     return JSON.stringify(this);
36.   }
37. }
38. 
39. // Call the class
40. function main() {
41.   const person = new Person("Poirot", "Hercule", 66);
42.   console.log("person=", person.toString(), typeof(person), person instanceof(Person));
43. }
44. 
45. // call to main
46. main();

Comentarios

  • línea 2: la palabra clave [clase] denota una clase;
  • líneas 5-9: la palabra clave [constructor] denota el constructor de la clase. Puede haber como máximo uno. Se utiliza para construir e inicializar una instancia de la clase. Nótese que no hay declaración de las propiedades [apellido, nombre, edad];
  • líneas 11-36: propiedades de la clase. Aquí vemos elementos ya tratados en la sección de objetos 4, página 44. Sólo difiere la sintaxis;
  • línea 41: creación de un objeto de tipo [Person]. A partir de ahora, el objeto [persona] se utiliza como objeto literal. [typeof (persona)] evalúa a "objeto" y la expresión [persona instanceof (Person)] es verdadera. Por lo tanto, es posible determinar el tipo exacto de una instancia de clase;

Resultados de la ejecución


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-01.js"
2. person = {"_lastName":"Poirot","_firstName":"Hercule","_age":66} object true

13.3. script [class-02]

Este script demuestra la capacidad de heredar de una clase utilizando la [extends] palabra clave.

Primero, movemos la clase [Persona] a un módulo llamado [Person.js]:


1. // class
2. class Person {
3. 
4.   // constructor
5.   constructor(lastName, firstName, age) {
6.     this.lastName = lastName;
7.     this.firstName = firstName;
8.     this.age = age;
9.   }
10. 
11.   // getters and setters
12.   get lastName() {
13.     return this._lastName;
14.   }
15.   set name(value) {
16.     this._name = value;
17.   }
18. 
19.   get firstName() {
20.     return this._first_name;
21.   }
22.   set firstName(value) {
23.     this._first_name = value;
24.   }
25. 
26.   get age() {
27.     return this._age;
28.   }
29.   set age(value) {
30.     this._age = value;
31.   }
32. 
33.   // toString as JSON
34.   toString() {
35.     return JSON.stringify(this);
36.   }
37. }
38. // export class
39. export default Person;
  • línea 39: exportamos la [Persona] clase para que los scripts puedan importarla;

El [clase-02] script crea una [Profesor] clase derivada de la [Persona] clase:


1. // imports
2. import Person from './Person';
3. 
4. // class
5. class Teacher extends Person {
6. 
7.   // constructor
8.   constructor(lastName, firstName, age, subject) {
9.     super(lastName, firstName, age);
10.     this.subject = subject;
11.   }
12. 
13.   // getters and setters
14.   get discipline() {
15.     return this._discipline;
16.   }
17.   set discipline(value) {
18.     this._discipline = value;
19.   }
20. 
21. }
22. 
23. // call the class
24. function main() {
25.   const teacher = new Teacher("Poirot", "Hercule", 66, "detective");
26.   console.log("teacher=", teacher.toString(), typeof (teacher), teacher instanceof Teacher);
27. }
28. 
29. // call to main
30. main();

Comentarios

  • línea 2: importamos la [Persona] clase del [Person.js] módulo, que se encuentra en la misma carpeta que [class-02];
  • línea 5: la [Profesor] clase extiende (hereda de) la [Persona] clase utilizando la [extiende] palabra clave: añade una [_sujeto] propiedad con los correspondientes métodos getter y setter;
  • líneas 8-11: el constructor de la [Profesor] clase recibe cuatro valores para inicializar las cuatro propiedades de la clase;
  • línea 9: la palabra clave [super] llama al constructor de la clase padre [Persona], que, por tanto, inicializará las propiedades [apellido, _primer_nombre, _edad];
  • línea 10: se inicializa la [_disciplina] propiedad perteneciente a la [Profesor] clase;
  • líneas 14-19: el getter y setter para la [_disciplina] propiedad;
  • línea 25: se crea un objeto de tipo [Profesor] ;
  • línea 26: utilizamos el método [profesor.toString()]. La clase [Profesor] no tiene este método. Por lo tanto, se utiliza automáticamente el método de su clase padre. Este método devuelve la expresión [JSON.stringify(this)], donde [this] será aquí un [Profesor] objeto, no un [Persona] objeto. Esto es lo que en programación orientada a objetos se conoce como polimorfismo de clases. Palabras mayores para JavaScript, que no es un lenguaje orientado a objetos. No obstante, JavaScript hace aquí lo que se espera de él: muestra correctamente un profesor;

Los resultados de la ejecución son los siguientes:


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-02.js"
2. teacher = {"_last_name":"Poirot","_first_name":"Hercule","_age":66,"_profession":"detective"} object true
  • línea 2: JavaScript reconoce correctamente que la variable [profesor] es de tipo [Profesor];

13.4. script [class-03]

El [clase-03] script muestra que una clase hija puede anular propiedades y métodos de su clase padre. Aquí, sobrescribimos el [toString] método de la clase padre:


1. // imports
2. import Person from './Person';
3. 
4. // class
5. class Teacher extends Person {
6. 
7.   // constructor
8.   constructor(lastName, firstName, age, subject) {
9.     super(lastName, firstName, age);
10.     this.subject = subject;
11.   }
12. 
13.   // getters and setters
14.   get discipline() {
15.     return this._discipline;
16.   }
17.   set discipline(value) {
18.     this._discipline = value;
19.   }
20. 
21.   // redefinition of toString
22.   toString() {
23.     return "[Teacher]" + JSON.stringify(this);
24.   }
25. }
26. 
27. // Call the class
28. function main() {
29.   const teacher = new Teacher("Poirot", "Hercule", 66, "detective");
30.   console.log("teacher=", teacher.toString(), typeof (teacher), teacher instanceof Teacher);
31. }
32. 
33. // call to main
34. main();

Los resultados de la ejecución son los siguientes:


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-03.js"
2. teacher = [Teacher]{"_last_name":"Poirot","_first_name":"Hercule","_age":66,"_profession":"detective"} object true

13.5. script [class-04]

El [clase-04] script demuestra de nuevo el polimorfismo en acción: donde una función espera un parámetro formal de tipo [Persona], podemos pasar un tipo derivado como [Profesor]. En efecto, en virtud de la derivación, el tipo [Profesor] tiene todos los atributos del tipo [Persona] .

Primero, aislamos el [Profesor] tipo en un [Profesor.js] módulo:


1. // imports
2. import Person from './Person';
3. 
4. // class
5. class Teacher extends Person {
6. 
7.   // constructor
8.   constructor(last_name, first_name, age, subject) {
9.     super(lastName, firstName, age);
10.     this.subject = subject;
11.   }
12. 
13.   // getters and setters
14.   get discipline() {
15.     return this._discipline;
16.   }
17.   set discipline(value) {
18.     this._discipline = value;
19.   }
20. 
21. }
22. 
23. // export class
24. export default Teacher;
  • línea 24: la [Profesor] clase se exporta para que otros scripts puedan importarla;

El [class-04] script es el siguiente:


1. // imports
2. import Teacher from './Teacher';
3. import Person from './Person';
4. 
5. // function accepting a person as a parameter
6. function show(person) {
7.   // in all cases
8.   console.log("parameter=", person.toString(), typeof(person));
9.   // instance of Person
10.   if (person instanceof Person) {
11.     console.log("person=", person.toString());
12.   }
13.   // instance of Teacher
14.   if (person is an instance of Teacher) {
15.     console.log("teacher=", person.toString());
16.   }
17. }
18. 
19. // Call show with a Teacher
20. show(new Teacher("Poirot", "Hercule", 66, "detective"));
21. show(new Person("Marple", "Miss", 70));
  • línea 6: la [show] función espera un [Persona] tipo o un tipo derivado;
  • línea 8: se muestra la cadena del parámetro y su tipo. Encontraremos [objeto];
  • líneas 10-16: podemos determinar si se trata de un [Persona] tipo o de un [Profesor] tipo. Por tanto, el código puede adaptarse al tipo real del parámetro;

Los resultados de la ejecución son los siguientes:


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-04.js"
2. parameter= {"_last_name":"Poirot","_first_name":"Hercule","_age":66,"_profession":"detective"} object
3. person = {"_last_name": "Poirot", "_first_name": "Hercule", "_age": 66, "_profession": "detective"}
4. teacher = {"_last_name":"Poirot","_first_name":"Hercule","_age":66,"_profession":"detective"}
5. parameter = {"_last_name": "Marple", "_first_name": "Miss", "_age": 70} object
6. person= {"_last_name":"Marple","_first_name":"Miss","_age":70}
  • líneas 4 y 6: JavaScript reconoce correctamente el tipo de instancias de clase;