
In un articolo precedente, abbiamo preso confidenza con TypeScript, la nuova frontiera del mondo Javascript, che ha introdotto una serie di novità sintattiche nel linguaggio più diffuso nel web “lato client”.
Vedremo ora i meccanismi che TypeScript mette a disposizione per la programmazione orientata agli oggetti ereditati, in buona parte, da EcmaScript6, recente evoluzione di Javascript.
Prima di passare all’esempio (di cui forniamo il listato completo), ricordiamo che il codice TypeScript deve essere compilato in Javascript tramite il transpiler offerto dal comando tsc ed il file prodotto potrà essere integrato in una pagina HTML. Comunque, TypeScript trova in Node.js il suo habitat naturale pertanto può essere impiegato anche in applicazioni stand-alone. Supponiamo di creare un file TypeScript di nome app.ts: dovremo prima compilarlo in Javascript
> tsc app.ts
e subito dopo potremo lanciarne il risultato con Node.js:
> node app.js
Classi e oggetti
Prima di istanziare oggetti, in TypeScript, è necessario creare le classi su cui essi si basano. Il linguaggio, a tal proposito, ha ereditato il costrutto class da EcmaScript6. Nell’esempio che proponiamo immaginiamo di avere una classe in grado di gestire fatture per clienti. Ogni articolo inserito in essa viene modellato con oggetti di classe Acquisto che contemplano una descrizione testuale del bene (ad esempio: “n. 10 pennarelli”) nonchè l’importo complessivo.
class Acquisto { private descrizione: string; private _prezzo: number; constructor(descrizione, prezzo) { this.descrizione=descrizione; this._prezzo=prezzo; } set prezzo(prezzo:number) { this._prezzo=prezzo; } get prezzo():number { return this._prezzo; } stampa():string { return "- "+this.descrizione+" "+this.prezzo+" euro"; } }
Notiamo che i due membri sono definiti con tanto di tipo di dato, caratteristica peculiare di TypeScript. E’ possibile applicare loro un livello di visibilità ristretta con il modificatore private che impedisce l’accesso alle proprietà dall’esterno della classe.
Il costruttore – metodo che in Programmazione Orientata agli Oggetti serve ad inizializzare il nuovo oggetto creato – deve necessariamente essere denominato constructor e può avere parametri in input. Il codice che abbiamo inserito al suo interno compie delle normali assegnazioni alle proprietà. Oltre al costruttore, si possono definire ulteriori metodi con tanto di tipo di ritorno come vediamo nel metodo stampa() che restituisce il formato stringa dell’oggetto Acquisto, compilando in pratica una riga della fattura:
stampa():string { return "- "+this.descrizione+" "+this.prezzo+" euro"; }
Quando dobbiamo gestire dall’esterno della classe un valore private si dovrebbero creare dei metodi pubblici per la lettura e la modifica corrispondenti, rispettivamente, ai classici getter e setter della Programmazione Orientata agli Oggetti. TypeScript, in stile .NET, offre gli operatori get e set per gli scopi analoghi che permetteranno di definire dei metodi in cui poter inserire analisi e formattazione sui dati con la possibilità di usarli come normali membri pubblici. Nella classe Acquisto l’abbiamo fatto per il prezzo con i seguenti passi:
- abbiamo definito un membro privato:
private _prezzo:number
- abbiamo definito una proprietà set in cui il valore passato in ingresso viene assegnato al membro privato:
set prezzo(prezzo:number) { this._prezzo=prezzo; }
- analogamente, con una proprietà get leggeremo il valore:
get prezzo():number { return this._prezzo; }
Proprietà gestite in questa modalità permettono di conservare i dati in forma privata ma evitano la scomodità sintattica di interagirvi tramite metodi come per i getter e setter, infatti potremo impostare e leggere il prezzo di un oggetto Acquisto così:
// assegnazione del prezzo acquisto.prezzo=45; // lettura del prezzo console.log(acquisto.prezzo);
In definitiva, gli oggetti della classe Acquisto possono essere usati nel seguente modo:
var primoAcquisto=new Acquisto("n. 10 penne", 12); console.log(primoAcquisto);
sintassi che ricorda molto i linguaggi tipici della Programmazione a Oggetti.
Sfruttando la classe Acquisto appena creata possiamo definirne un’altra, denominata Fattura, che presenterà due membri: una stringa contenente il nome del cliente ed un array di oggetti Acquisto grazie al quale potremo procedere alla stampa complessiva ed il calcolo del totale.
class Fattura { private cliente: string; private acquisti:Acquisto[]=[]; constructor(cliente: string) { this.cliente=cliente; } aggiungiAcquisto(nuovo:Acquisto) { this.acquisti.push(nuovo); } stampaFattura() { console.log(this.cliente); for (let s of this.acquisti) { console.log(s.stampa()); } console.log("Totale: "+this.importoTotale+" euro"); } get importoTotale():number { var totale:number=0.0; for (let s of this.acquisti) { totale+=s.prezzo; } return totale; } }
Oltre alla definizione del secondo membro come array di oggetti, gli altri aspetti della classe sono stati già discussi precedentemente in questo tutorial. Notiamo solo un paio di aspetti:
- l’operatore get è stato utilizzato per gestire il calcolo dell’importo totale, non un normale membro privato. La comodità in questo caso consiste solo nel risparmio delle parentesi tonde al momento della sua invocazione nel metodo stampaFattura();
- il ciclo for utilizzato usa la sintassi for-of in stile EcmaScript6 che permette di ciclare comodamente tra gli oggetti inseriti in un array.
Conclusione dell’esempio
Per sperimentare le nostre classi, possiamo scrivere le seguenti righe di codice che creeranno un oggetto Fattura, vi inseriranno degli acquisti ed infine richiederanno una semplice stampa del documento:
var fattura=new Fattura("Ditta Rossi s.r.l."); fattura.aggiungiAcquisto(new Acquisto("10 penne", 10)); fattura.aggiungiAcquisto(new Acquisto("zaino", 37.5)); fattura.aggiungiAcquisto(new Acquisto("USB drive 64 GB", 16.39)); fattura.aggiungiAcquisto(new Acquisto("12 quaderni", 8)); fattura.stampaFattura();
Quello che segue è l’output prodotto:
Ditta Rossi s.r.l. - 10 penne 10 euro - zaino 37.5 euro - USB drive 64 GB 16.39 euro - 12 quaderni 8 euro Totale: 71.89 euro
Il tutorial che qui si conclude ha introdotto la programmazione ad oggetti in TypeScript: l’argomento è fondamentale non solo per la sua utilità nella vita professionale ma soprattutto perchè era una delle grandi sfide che attendeva il linguaggio e possiamo dire che TypeScript se l’è cavata piuttosto bene.
Nei prossimi tutorial, impareremo altri aspetti di questa versione moderna del Javascript, lo approfondiremo per impiegarlo poi in contesti più complessi.
Continuate a seguirci!
No Responses to “Programmare a oggetti in TypeScript”