Classi ES6: class, extends, super, static, private fields (#)
Zucchero sintattico su prototype, private class fields, static blocks
Nella pillola sulla prototype chain abbiamo visto come JavaScript condivide metodi tra oggetti tramite Object.create() e Function.prototype. La sintassi class, introdotta con ES6, non cambia questo meccanismo: le classi sono principalmente zucchero sintattico sopra l'ereditarietà a prototipi già esistente in JavaScript.
E' come passare da un impianto elettrico con fili scoperti a uno con prese e interruttori standard. L'elettricità che scorre dentro è esattamente la stessa; cambia solo quanto è comodo, leggibile e sicuro collegare le cose.
1. class: una sintassi più chiara, non un nuovo modello
class Persona {
constructor(nome) {
this.nome = nome;
}
saluta() {
return `Ciao, sono ${this.nome}`;
}
}
const ada = new Persona("Ada");
ada.saluta(); // "Ciao, sono Ada"
Dietro le quinte, saluta viene installato su Persona.prototype, esattamente come avremmo fatto a mano con Persona.prototype.saluta = function() {...}. La differenza è tutta nella leggibilità: raggruppare costruttore e metodi in un unico blocco, invece di sparpagliarli.
2. extends e super: ereditare da un'altra classe
extends fa ereditare una classe da un'altra. super() richiama il costruttore della classe padre; super.metodo() richiama un metodo del padre, utile per estendere un comportamento invece di riscriverlo da zero.
class Animale {
constructor(nome) {
this.nome = nome;
}
descrizione() {
return `${this.nome} e' un animale`;
}
}
class Cane extends Animale {
descrizione() {
return super.descrizione() + ", nello specifico un cane";
}
}
new Cane("Fido").descrizione();
// "Fido e' un animale, nello specifico un cane"
Una regola precisa dal manuale: una classe può estendere solo una classe alla volta, niente ereditarietà multipla, proprio per evitare l'ambiguità nota come «problema del diamante».
3. static: appartiene alla classe, non alle istanze
Un membro static viene installato sulla classe stessa, non sulle singole istanze create con new. Utile per funzioni di utilità legate al concetto della classe, ma non a un oggetto specifico.
class Cerchio {
static PI_GRECO = 3.14159;
static areaDaRaggio(r) {
return Cerchio.PI_GRECO * r * r;
}
}
Cerchio.areaDaRaggio(5); // richiamato sulla classe, non su un'istanza
4. Private fields (#): davvero privati, non solo per convenzione
Prefissare un campo con # lo rende privato, non un'etichetta informale come _privato (una convenzione che non impedisce nulla), ma un vincolo imposto dal linguaggio. MDN chiama questo comportamento «hard private»: il campo è visibile solo dentro il corpo della classe che lo dichiara.
class ContoBancario {
#saldo = 0; // privato: nessuno fuori può leggerlo o scriverlo
deposita(importo) {
this.#saldo += importo;
return this.#saldo;
}
}
const conto = new ContoBancario();
conto.deposita(100); // 100
conto.#saldo; // SyntaxError: campo privato non accessibile da qui
Punto importante: nemmeno una sottoclasse (con extends) può accedere ai campi privati della classe padre. Sono vincolati al corpo della classe in cui sono scritti, non trasmessi lungo la catena di ereditarietà.
Esempio nella vita reale: «_saldo» con il trattino basso è come scrivere «riservato» su un cassetto senza chiave, un invito a non aprirlo, che chiunque può comunque ignorare. «#saldo» è lo stesso cassetto con una vera serratura: nessuno, nemmeno un erede della famiglia, può aprirlo se non ha la combinazione scritta dentro quella stanza.
In sintesi
| Elemento | Cosa fa | Da ricordare |
|---|---|---|
class |
Sintassi più leggibile sopra il prototype esistente | Non è un nuovo modello a oggetti |
extends / super |
Eredita da un'altra classe, richiama il padre | Solo singola ereditarietà, non multipla |
static |
Appartiene alla classe, non alle istanze | Richiamato su NomeClasse, non su un oggetto |
#campo |
Privato imposto dal linguaggio (hard private) | Nemmeno le sottoclassi ci accedono |
Le classi non sostituiscono i prototipi: li vestono con una sintassi più familiare a chi arriva da altri linguaggi. Capire cosa succede sotto, extends collega prototipi, i metodi finiscono su .prototype, evita sorprese quando un giorno il codice si comporta in modo inatteso.
Commenti (0)
Registrati per commentare, fare domande e proporre l'argomento della prossima pillola (oppure accedi se hai già un account).
Nessun commento. Sii il primo a scrivere qualcosa.