Ya hemos visto una pequeña introducción a las clases y la herencia en JavaScript. En esta tercera parte nos toca revisar los métodos y atributos estáticos. Primero pasemos a definir que es un miembro estático de manera más o menos oficial:
Un miembro estático es aquel que reside en una clase sin requerir una instancia de esta para ser ejecutado. De forma que hay sólo una copia de éste, y se puede llamar sin tener objetos de la clase.
Yo mismo, resumiendo un poco lo que se habla en otros muchos sitios 😂
Para declarar un miembro estático, no os podéis imaginar la palabra reservada que se va a usar... así es, se utiliza "static
".
Bueno, pongámonos serios y pasemos a ver un ejemplo de código:
class Operation {
static add(sum1, sum2) {
return sum1 + sum2;
}
addMultiple(sum1, sum2, sum3, sum4) {
return Operations.add(sum1, sum2) + Operations.add(sum3, sum4);
}
}
const operation = new Operation();
operation.addMultiple(45, 4535, 785, 2934); // 8299
Operations.add(1438, 2438); // 3876
Partiendo del código anterior, podemos ver como con static
, hacemos que un método pase a ser estático, y que tanto para llamarlo desde dentro de la clase como desde fuera, se indicará el nombre de la clase y el nombre del atributo o método al que acceder.
En este caso, sólo hay definido un método add()
, es decir, al contrario que ocurre con un método normal (también lo podemos aplicar a los atributos), no habrá un objeto con su propia "copia" del método, sino que habrá uno global para todos los objetos.
¿Esto cómo aplica a la herencia? Pues veamos otro ejemplo:
class Article {
static taxPercent = 1.1;
#name;
#price;
constructor(name, price) {
this.#name = name;
this.#price = price;
}
get Name() {
return this.#name;
}
get Price() {
return this.#price;
}
calculatePrice() {
return this.#price * Article.taxPercent;
}
}
class DeluxeArticle extends Article {
static taxPercent = 1.21;
}
const article = new Article("Osito de peluche", 10);
article.calculatePrice(); // 11
deluxeArticle = new DeluxeArticle("Lijadora", 100);
deluxeArticle.calculatePrice(); // 110
¡Hey espera! ¿Por qué el cálculo del precio de la lijadora devuelve 110, en lugar de 121?. Esto es porque en el método de la clase padre tenemos Article.taxPercent
. En este caso al ser un elemento estático, no sobre-escribimos dicho valor, como si podría dar pie con miembros no estáticos. Es por ello que en el cálculo estamos llamando a taxPercent
del padre. Si fuera necesario llamar al nuevo taxPercent
, tendríamos que sobreescribir el método de DeluxeArticle
de forma que quedara tal que así:
class DeluxeArticle extends Article {
static taxPercent = 1.21;
calculatePrice() {
return this.Price * DeluxeArticle.taxPercent;
}
}
Ahora si estamos llamando al atributo estático de nuestra clase. En resumen, en el código de ejemplo estamos teniendo dos atributos estáticos con el mismo nombre, uno accesible con Article.taxPercent
, y el otro con DeluxeArticle.taxPercent
. Es más podemos acceder a uno u otro indistintamente según nos haga falta, siempre anteponiendo el nombre de la clase que lo contiene.
Con todo lo visto, es muy sencillo pasar a implementar el conocido patrón singleton en JavaScript:
class MySingleton {
static #instance = null;
// Añadimos un atributo nombre para poder hacer pruebas más adelante 😉
#name;
static getInstance() {
if (!MySingleton.#instance) {
MySingleton.#instance = new MySingleton();
}
return MySingleton.#instance;
}
set Name(name) {
this.#name = name;
}
get Name() {
return this.#name;
}
}
const instance1 = MySingleton.getInstance();
const instance2 = MySingleton.getInstance();
instance1.Name = "Soy un singleton";
instance1.Name; // Soy un singleton
instance2.Name; // Soy un singleton
La pena es que no se puedan tener constructores privados en JavaScript para evitar instancias ajenas que no vayan por el método getInstance()
.
Más artículos de esta serie: Parte 1. Clases y Parte 2. Herencia
Comparte este artículo con quien quieras
Ya hemos visto una pequeña introducción a las clases y la herencia en JavaScript. En esta tercera parte nos toca revisar los métodos y atributos estáticos. Primero pasemos a definir que es un miembro estático de manera más o menos oficial:
Para declarar un miembro estático, no os podéis imaginar la palabra reservada que se va a usar... así es, se utiliza "
static
".Bueno, pongámonos serios y pasemos a ver un ejemplo de código:
Partiendo del código anterior, podemos ver como con
static
, hacemos que un método pase a ser estático, y que tanto para llamarlo desde dentro de la clase como desde fuera, se indicará el nombre de la clase y el nombre del atributo o método al que acceder.En este caso, sólo hay definido un método
add()
, es decir, al contrario que ocurre con un método normal (también lo podemos aplicar a los atributos), no habrá un objeto con su propia "copia" del método, sino que habrá uno global para todos los objetos.¿Esto cómo aplica a la herencia? Pues veamos otro ejemplo:
¡Hey espera! ¿Por qué el cálculo del precio de la lijadora devuelve 110, en lugar de 121?. Esto es porque en el método de la clase padre tenemos
Article.taxPercent
. En este caso al ser un elemento estático, no sobre-escribimos dicho valor, como si podría dar pie con miembros no estáticos. Es por ello que en el cálculo estamos llamando ataxPercent
del padre. Si fuera necesario llamar al nuevotaxPercent
, tendríamos que sobreescribir el método deDeluxeArticle
de forma que quedara tal que así:Ahora si estamos llamando al atributo estático de nuestra clase. En resumen, en el código de ejemplo estamos teniendo dos atributos estáticos con el mismo nombre, uno accesible con
Article.taxPercent
, y el otro conDeluxeArticle.taxPercent
. Es más podemos acceder a uno u otro indistintamente según nos haga falta, siempre anteponiendo el nombre de la clase que lo contiene.Con todo lo visto, es muy sencillo pasar a implementar el conocido patrón singleton en JavaScript:
La pena es que no se puedan tener constructores privados en JavaScript para evitar instancias ajenas que no vayan por el método
getInstance()
.Más artículos de esta serie: Parte 1. Clases y Parte 2. Herencia
jose