La programmazione ad oggetti in JavaScript si basa su un modello non sempre ben compreso dagli sviluppatori che conoscono linguaggi di programmazione come C++, Java o C#. Il modello di programmazione ad oggetti in JavaScript non prevede il concetto di classe, ma si basa direttamente sugli oggetti, su modelli di oggetti (prototipi) e su funzioni che generato oggetti (costruttori).
Le specifiche ECMAScript 6 hanno introdotto il costrutto sintattico class che tenta di colmare il gap tra la programmazione ad oggetti classica e quella prototipale di JavaScript, ma non si tratta di un cambio del modello di programmazione, piuttosto di una semplificazione sintattica.
Classi
TypeScript prevede il supporto delle classi estendendo la nuova sintassi ES6 e rendendola ancora più vicina alla programmazione ad oggetti classica.
Consideriamo il seguente codice:
/* definizione di classe TypeScript
*/
class Persona {
nome: string;
cognome: string;
constructor(nome: string, cognome: string) {
this.nome = nome;
this.cognome = cognome;
}
visualizzaNomeCognome() {
return this.nome + ' ' + this.cognome;
}
}
L'esempio definisce una classe Persona
utilizzando il costrutto class
. Al suo interno possiamo vedere la dichiarazione di due proprietà di tipo stringa, nome
e cognome
, la presenza di un costruttore, che assegna i due parametri passati alle rispettive proprietà, e la dichiarazione del metodo visualizzaNomeCognome()
che restituisce la concatenazione del nome e del cognome.
La sintassi utilizzata per definire la classe è molto simile a quella di ES6, come possiamo vedere di seguito:
/* definizione di classe ES6
*/
class Persona {
constructor(nome, cognome) {
this.nome = nome;
this.cognome = cognome;
}
visualizzaNomeCognome() {
return this.nome + ' ' + this.cognome;
}
}
Ma TypeScript la estende per renderla molto più simile a quella dei linguaggi di programmazione ad oggetti tradizionali. A parte la presenza dei tipi di dato, infatti, possiamo ad esempio notare la dichiarazione delle proprietà nome
e cognome
, possibilità non prevista dalle classi di ECMAScript 6.
Come per ES6, il nome constructor è riservato per la definizione di un costruttore per la classe.
La creazione di un'istanza della classe Persona
viene effettuata tramite l'operatore new:
var marioRossi = new Persona("Mario", "Rossi");
console.log(marioRossi.visualizzaNomeCognome());
Membri pubblici e privati
Abbiamo visto come le classi di TypeScript prevedano la dichiarazione di proprietà. Se non diversamente specificato, le proprietà di una classe sono pubbliche, cioè accessibili dal codice esterno alla classe, come possiamo vedere dal seguente esempio:
class Persona {
nome: string;
cognome: string;
visualizzaNomeCognome() {
return this.nome + ' ' + this.cognome;
}
}
var marioRossi = new Persona();
marioRossi.nome = "Mario";
marioRossi.cognome = "Rossi";
console.log(marioRossi.visualizzaNomeCognome()); //Mario Rossi
Il discorso sulla visibilità dei metodi è analogo. Infatti, anche il metodo visualizzaNomeCognome()
è pubblico, infatti lo utilizziamo per visualizzare la concatenazione delle proprietà nome
e cognome
.
Se premettiamo la parola chiave private ai membri di una classe li rendiamo non accessibili dall'esterno. Ad esempio, la seguente dichiarazione renderà inaccessibile il metodo visualizzaNomeCognome()
:
class Persona {
nome: string;
cognome: string;
private visualizzaNomeCognome() {
return this.nome + ' ' + this.cognome;
}
}
Quindi, ogni tentativo di utilizzare il metodo a partire da un'istanza della classe genererà un errore del compilatore, come possiamo vedere direttamente in Playground:
Da notare che la visibilità privata di un membro di una classe non viene implementata internamente con le classiche tecniche JavaScript che sfruttano la closure, ma la visibilità viene risolta semplicemente a tempo di compilazione con un'analisi statica del codice.