Skip to content

13. Las clases

Image

Aquí presentamos las clases de ECMAScript 6. En primer lugar, mostramos que las funciones ya pueden utilizarse como clases.

13.1. script [class-00]

El siguiente script muestra un uso poco habitual de las funciones. Aquí se utilizan como objetos.


'use strict';
// una función se puede utilizar como un objeto

// una carcasa vacía
function f() {

}
// a la que se le asignan propiedades desde el exterior
f.prop1 = "val1";
f.show = function () {
  console.log(this.prop1);
}
// uso de f
f.show();

// una función g que funciona como una clase
function g() {
  this.prop2 = "val2";
  this.show = function () {
    console.log(this.prop2);
  }
}
// instanciación de la función con [new]
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 el exterior;
  • línea 14: uso de la función (objeto) f. Fíjate en que no se escribe [f()], sino simplemente [f]. Aquí se utiliza la notación de un objeto;
  • líneas 17-22: se define 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


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

ES6 ha introducido el concepto de clase, lo que nos permite ahora evitar tener que recurrir a funciones para obtener clases.

13.2. script [class-01]

El script [class-01] presenta una clase [Personne]:


// clase
class Personne {

  // constructor
  constructor(nom, prénom, âge) {
    this.nom = nom;
    this.prénom = prénom;
    this.âge = âge;
  }

  // métodos getter y setter
  get nom() {
    return this._nom;
  }
  set nom(value) {
    this._nom = value;
  }

  get prénom() {
    return this._prénom;
  }
  set prénom(value) {
    this._prénom = value;
  }

  get âge() {
    return this._âge;
  }
  set âge(value) {
    this._âge = value;
  }

  // toString en JSON
  toString() {
    return JSON.stringify(this);
  }
}

// llamada a la clase
function main() {
  const personne = new Personne("Poirot", "Hercule", 66);
  console.log("personne=", personne.toString(), typeof (personne), personne instanceof (Personne));
}

// llamada a main
main();

Comentarios

  • línea 2: la palabra clave [class] designa una clase;
  • líneas 5-9: la palabra clave [constructor] designa el constructor de la clase. Solo puede haber uno como máximo. Sirve para crear e inicializar una instancia de la clase. Ten en cuenta que no hay ninguna declaración de las propiedades [nom, prénom, âge];
  • líneas 11-36: propiedades de la clase. Aquí encontramos elementos que ya hemos visto en el apartado sobre objetos 4, página 44. Solo difiere la sintaxis;
  • línea 41: creación de un objeto de tipo [Personne]. A partir de ahora, el objeto [personne] se utiliza como un objeto literal. [typeof (personne)] es igual a «object» y la expresión [personne instanceof (Personne)] es verdadera. Por lo tanto, es posible conocer el tipo exacto de una instancia de clase;

Resultados de la ejecución


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-01.js"
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66} object true

13.3. script [class-02]

Este script muestra la posibilidad de heredar de una clase con la palabra clave [extends].

En primer lugar, aislamos la clase [Personne] en un módulo [Personne.js]:


// clase
class Personne {

  // constructor
  constructor(nom, prénom, âge) {
    this.nom = nom;
    this.prénom = prénom;
    this.âge = âge;
  }

  // getters y setters
  get nom() {
    return this._nom;
  }
  set nom(value) {
    this._nom = value;
  }

  get prénom() {
    return this._prénom;
  }
  set prénom(value) {
    this._prénom = value;
  }

  get âge() {
    return this._âge;
  }
  set âge(value) {
    this._âge = value;
  }

  // toString en JSON
  toString() {
    return JSON.stringify(this);
  }
}
// clase de exportación
export default Personne;
  • línea 39: exportamos la clase [Personne] para que otros scripts puedan importarla;

El script [class-02] crea una clase [Enseignant] derivada de la clase [Personne]:


// importaciones
import Personne from './Personne';

// clase
class Enseignant extends Personne {

  // constructor
  constructor(nom, prénom, âge, discipline) {
    super(nom, prénom, âge);
    this.discipline = discipline;
  }

  // getters y setters
  get discipline() {
    return this._discipline;
  }
  set discipline(value) {
    this._discipline = value;
  }

}

// llamada a la clase
function main() {
  const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
  console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}

// llamada a main
main();

Comentarios

  • línea 2: se importa la clase [Personne] desde el módulo [Personne.js], que se encuentra en la misma carpeta que [class-02];
  • línea 5: la clase [Enseignant] extiende (hereda de) la clase [Personne] con la palabra clave [extends]: le añade una propiedad [_discipline] con los getter y setter correspondientes;
  • líneas 8-11: el constructor de la clase [Enseignant] recibe cuatro valores para inicializar las cuatro propiedades de la clase;
  • línea 9: la palabra clave [super] invoca al constructor de la clase padre [Personne], que, por lo tanto, inicializará las propiedades [_nom, _prénom, _âge];
  • línea 10: se inicializa la propiedad [_discipline], que pertenece a la clase [Enseignant];
  • líneas 14-19: el getter y el setter de la propiedad [_discipline];
  • línea 25: se crea un objeto de tipo [Enseignant];
  • línea 26: se utiliza el método [enseignant.toString()]. La clase [Enseignant] no dispone de este método. En ese caso, se utiliza automáticamente el de su clase padre. Este método hace que la expresión [JSON.stringify(this)] —donde [this] será aquí un objeto [Enseignant] y no un objeto [Personne]— se resuelva correctamente. Esto es lo que en programación orientada a objetos se denomina polimorfismo de clases. Un término complicado para JavaScript, que no es un lenguaje orientado a objetos. No obstante, JavaScript hace aquí lo que se espera de él: muestra correctamente a un profesor;

Los resultados de la ejecución son los siguientes:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-02.js"
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true
  • línea 2: JavaScript reconoce correctamente que la variable [enseignant] es de tipo [Enseignant];

13.4. script [class-03]

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


// importaciones
import Personne from './Personne';

// clase
class Enseignant extends Personne {

  // constructor
  constructor(nom, prénom, âge, discipline) {
    super(nom, prénom, âge);
    this.discipline = discipline;
  }

  // getters y setters
  get discipline() {
    return this._discipline;
  }
  set discipline(value) {
    this._discipline = value;
  }

  // redefinición de toString
  toString() {
    return "[Enseignant]" + JSON.stringify(this);
  }
}

// llamada a la clase
function main() {
  const enseignant = new Enseignant("Poirot", "Hercule", 66, "détective");
  console.log("enseignant=", enseignant.toString(), typeof (enseignant), enseignant instanceof Enseignant);
}

// llamada a main
main();

Los resultados de la ejecución son los siguientes:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-03.js"
enseignant= [Enseignant]{"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object true

13.5. script [class-04]

El script [class-04] vuelve a mostrar el polimorfismo en acción: cuando una función espera un parámetro formal de tipo [Personne], se puede pasar un tipo derivado como [Enseignant]. De hecho, debido a la derivación, el tipo [Enseignant] tiene todos los atributos del tipo [Personne].

En primer lugar, aislamos el tipo [Enseignant] en un módulo [Enseignant.js]:


// importaciones
import Personne from './Personne';

// clase
class Enseignant extends Personne {

  // constructor
  constructor(nom, prénom, âge, discipline) {
    super(nom, prénom, âge);
    this.discipline = discipline;
  }

  // getter y setter
  get discipline() {
    return this._discipline;
  }
  set discipline(value) {
    this._discipline = value;
  }

}

// clase de exportación
export default Enseignant;
  • línea 24: se exporta la clase [Enseignant] para que otros scripts puedan importarla;

El script [class-04] es el siguiente:


// importaciones
import Enseignant from './Enseignant';
import Personne from './Personne';

// función que acepta una persona como parámetro
function show(personne) {
  // en todos los casos
  console.log("paramètre=", personne.toString(), typeof (personne));
  // instancia de Persona
  if (personne instanceof Personne) {
    console.log("personne=", personne.toString());
  }
  // instancia de Profesor
  if (personne instanceof Enseignant) {
    console.log("enseignant=", personne.toString());
  }
}

// llamada a «show» con un profesor
show(new Enseignant("Poirot", "Hercule", 66, "détective"));
show(new Personne("Marple", "Miss", 70));
  • línea 6: la función [show] espera un tipo [Personne] o derivado;
  • línea 8: se muestra la cadena del parámetro y su tipo. Aparecerá [object];
  • líneas 10-16: se puede determinar si se trata de un tipo [Personne] o de un tipo [Enseignant]. Por lo tanto, el código se puede adaptar al tipo real del parámetro;

Los resultados de la ejecución son los siguientes:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\classes\class-04.js"
paramètre= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"} object
personne= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
enseignant= {"_nom":"Poirot","_prénom":"Hercule","_âge":66,"_discipline":"détective"}
paramètre= {"_nom":"Marple","_prénom":"Miss","_âge":70} object
personne= {"_nom":"Marple","_prénom":"Miss","_âge":70}
  • líneas 4 y 6: JavaScript reconoce correctamente el tipo de las instancias de clase;