{"id":12397,"date":"2017-04-07T18:30:34","date_gmt":"2017-04-07T16:30:34","guid":{"rendered":"http:\/\/www.devapp.it\/wordpress\/?p=12397"},"modified":"2017-04-07T18:30:34","modified_gmt":"2017-04-07T16:30:34","slug":"programmare-a-oggetti-in-typescript","status":"publish","type":"post","link":"https:\/\/www.devapp.it\/wordpress\/programmare-a-oggetti-in-typescript\/","title":{"rendered":"Programmare a oggetti in TypeScript"},"content":{"rendered":"<p>In un <a href=\"http:\/\/www.devapp.it\/wordpress\/introduzione-a-typescript\/\">articolo precedente<\/a>, abbiamo preso confidenza con\u00a0TypeScript, la nuova frontiera del mondo Javascript, che ha introdotto una serie di novit\u00e0 sintattiche nel \u00a0linguaggio pi\u00f9 diffuso nel web &#8220;lato client&#8221;.<\/p>\n<p>Vedremo ora i meccanismi che TypeScript mette \u00a0a disposizione per la programmazione orientata agli oggetti ereditati, in\u00a0buona parte, da\u00a0EcmaScript6, recente\u00a0evoluzione di\u00a0Javascript.<\/p>\n<p>Prima di passare all&#8217;esempio (di cui forniamo il\u00a0<a href=\"http:\/\/www.devapp.it\/wordpress\/wp-content\/uploads\/2016\/09\/Esempio-OOP-TypeScript.zip\" target=\"_blank\">listato completo<\/a>),\u00a0ricordiamo che il codice TypeScript deve essere compilato in Javascript tramite il <em>transpiler<\/em> offerto dal comando <em>tsc<\/em> ed il file prodotto potr\u00e0 essere integrato in una pagina HTML. Comunque, TypeScript trova\u00a0in <a href=\"http:\/\/www.devapp.it\/wordpress\/introduzione-a-node-js\/\" target=\"_blank\">Node.js<\/a> il suo habitat naturale pertanto pu\u00f2 essere impiegato anche in applicazioni stand-alone.\u00a0Supponiamo di creare un file\u00a0TypeScript di\u00a0nome <em>app.ts:<\/em> dovremo prima compilarlo in Javascript<\/p>\n<pre class=\"lang:sh decode:true\">&gt; tsc app.ts<\/pre>\n<p>e subito dopo potremo lanciarne il risultato con Node.js:<\/p>\n<pre class=\"lang:sh decode:true\">&gt; node app.js<\/pre>\n<h2>Classi e oggetti<\/h2>\n<p>Prima di istanziare oggetti, in TypeScript, \u00e8 necessario creare le\u00a0classi su cui essi si basano. Il linguaggio, a tal proposito, ha ereditato il costrutto <strong>class<\/strong> da EcmaScript6. Nell&#8217;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: &#8220;n. 10 pennarelli&#8221;) nonch\u00e8\u00a0l&#8217;importo complessivo.<\/p>\n<pre class=\"lang:js decode:true\">class Acquisto\r\n{\r\n    private descrizione: string;\r\n    private _prezzo: number;\r\n\r\n    constructor(descrizione, prezzo)\r\n    {\r\n        this.descrizione=descrizione;\r\n        this._prezzo=prezzo;\r\n    }\r\n\r\n    set prezzo(prezzo:number)\r\n    {\r\n        this._prezzo=prezzo;\r\n    }\r\n\r\n    get prezzo():number\r\n    {\r\n        return this._prezzo;\r\n    }\r\n\r\n    stampa():string\r\n    {\r\n        return \"- \"+this.descrizione+\"   \"+this.prezzo+\" euro\";\r\n    }\r\n}<\/pre>\n<p>Notiamo che i due membri sono definiti con tanto di tipo di dato, caratteristica peculiare di TypeScript. E&#8217; possibile applicare loro un livello di visibilit\u00e0 ristretta con il modificatore <strong>private<\/strong> che impedisce l&#8217;accesso alle propriet\u00e0 dall&#8217;esterno della classe.<\/p>\n<p>Il <strong>costruttore<\/strong> &#8211; metodo che in\u00a0Programmazione Orientata agli Oggetti serve ad inizializzare il nuovo oggetto creato &#8211; deve necessariamente essere denominato <em>constructor<\/em> e pu\u00f2 avere parametri in input. Il codice che abbiamo inserito al suo interno compie delle normali assegnazioni alle propriet\u00e0. Oltre al costruttore, si possono definire ulteriori metodi con tanto di tipo di ritorno come vediamo nel metodo <em>stampa()<\/em> che restituisce il formato stringa dell&#8217;oggetto Acquisto, compilando in pratica una riga della fattura:<\/p>\n<pre class=\"lang:js decode:true\"> stampa():string\r\n    {\r\n        return \"- \"+this.descrizione+\"   \"+this.prezzo+\" euro\";\r\n    }<\/pre>\n<p>Quando dobbiamo gestire dall&#8217;esterno della classe un valore <em>private<\/em> si dovrebbero creare dei metodi pubblici per la lettura\u00a0e la modifica\u00a0corrispondenti, rispettivamente, ai classici getter e setter della Programmazione Orientata agli Oggetti. TypeScript, in stile .NET, offre gli <strong>operatori get e set<\/strong> per gli scopi analoghi che permetteranno di definire dei metodi in cui poter inserire analisi\u00a0e formattazione sui\u00a0dati con la possibilit\u00e0 di usarli come normali membri pubblici. Nella classe Acquisto l&#8217;abbiamo fatto per il prezzo con i seguenti passi:<\/p>\n<ul>\n<li>abbiamo definito un membro privato:\n<pre class=\"lang:js decode:true\">private _prezzo:number<\/pre>\n<\/li>\n<li>abbiamo definito una propriet\u00e0 set in cui il valore passato in ingresso viene assegnato al membro privato:\n<pre class=\"lang:js decode:true\"> set prezzo(prezzo:number)\r\n    {\r\n        this._prezzo=prezzo;\r\n    }<\/pre>\n<\/li>\n<li>analogamente, con una propriet\u00e0 get leggeremo il valore:\n<pre class=\"lang:js decode:true\">get prezzo():number\r\n    {\r\n        return this._prezzo;\r\n    }<\/pre>\n<\/li>\n<\/ul>\n<p>Propriet\u00e0 gestite in questa modalit\u00e0 permettono di conservare i dati in forma privata ma evitano la scomodit\u00e0 sintattica di interagirvi tramite metodi come per i <em>getter<\/em> e <em>setter<\/em>, infatti potremo impostare e leggere il prezzo di un oggetto Acquisto cos\u00ec:<\/p>\n<pre class=\"lang:js decode:true\">\/\/ assegnazione del prezzo\r\nacquisto.prezzo=45;\r\n\r\n\/\/ lettura del prezzo\r\nconsole.log(acquisto.prezzo);<\/pre>\n<p>In definitiva, gli oggetti della classe Acquisto possono essere usati nel seguente modo:<\/p>\n<pre class=\"lang:js decode:true\">var primoAcquisto=new Acquisto(\"n. 10 penne\", 12);\r\nconsole.log(primoAcquisto);<\/pre>\n<p>sintassi che ricorda molto i linguaggi tipici della Programmazione a Oggetti.<\/p>\n<p>Sfruttando la classe Acquisto appena creata possiamo definirne un&#8217;altra, denominata Fattura, che presenter\u00e0 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.<\/p>\n<pre class=\"lang:js decode:true\">class Fattura\r\n{\r\n    private cliente: string;\r\n    private acquisti:Acquisto[]=[];\r\n\r\n    constructor(cliente: string)\r\n    {\r\n        this.cliente=cliente;\r\n    }\r\n\r\n    aggiungiAcquisto(nuovo:Acquisto)\r\n    {\r\n        this.acquisti.push(nuovo);\r\n    }\r\n\r\n    stampaFattura()\r\n    {\r\n        console.log(this.cliente);\r\n        for (let s of this.acquisti)\r\n        {\r\n            console.log(s.stampa());\r\n        }\r\n        console.log(\"Totale: \"+this.importoTotale+\" euro\");\r\n    }\r\n\r\n    get importoTotale():number\r\n    {\r\n        var totale:number=0.0;\r\n        for (let s of this.acquisti)\r\n        {\r\n            totale+=s.prezzo;\r\n        }\r\n        return totale;\r\n    }\r\n}<\/pre>\n<p>Oltre alla definizione del secondo membro come array di oggetti, gli altri aspetti della classe sono\u00a0stati gi\u00e0 discussi precedentemente in questo tutorial.\u00a0Notiamo solo un paio di aspetti:<\/p>\n<ul>\n<li>l&#8217;<strong>operatore get<\/strong> \u00e8 stato utilizzato per gestire il calcolo dell&#8217;importo totale, non un normale membro privato. La comodit\u00e0 in questo caso consiste solo nel risparmio delle parentesi tonde al momento della sua invocazione nel metodo <em>stampaFattura()<\/em>;<\/li>\n<li>il ciclo <em>for<\/em> utilizzato usa la sintassi <strong>for-of<\/strong> in stile EcmaScript6 che permette di ciclare comodamente tra gli oggetti inseriti in un array.<\/li>\n<\/ul>\n<h2>Conclusione dell&#8217;esempio<\/h2>\n<p>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:<\/p>\n<pre class=\"lang:js decode:true\">var fattura=new Fattura(\"Ditta Rossi s.r.l.\");\r\nfattura.aggiungiAcquisto(new Acquisto(\"10 penne\", 10));\r\nfattura.aggiungiAcquisto(new Acquisto(\"zaino\", 37.5));\r\nfattura.aggiungiAcquisto(new Acquisto(\"USB drive 64 GB\", 16.39));\r\nfattura.aggiungiAcquisto(new Acquisto(\"12 quaderni\", 8));\r\n\r\nfattura.stampaFattura();<\/pre>\n<p>Quello che segue \u00e8 l&#8217;output prodotto:<\/p>\n<pre class=\"lang:js decode:true\">Ditta Rossi s.r.l.\r\n- 10 penne   10 euro\r\n- zaino   37.5 euro\r\n- USB drive 64 GB   16.39 euro\r\n- 12 quaderni   8 euro\r\nTotale: 71.89 euro\r\n<\/pre>\n<p>Il tutorial che qui si conclude ha introdotto la programmazione ad oggetti in TypeScript: l&#8217;argomento \u00e8 fondamentale non solo per la sua utilit\u00e0 nella vita professionale ma soprattutto perch\u00e8 era una delle grandi sfide che attendeva il linguaggio e possiamo dire che TypeScript se l&#8217;\u00e8 cavata piuttosto bene.<\/p>\n<p>Nei prossimi tutorial, impareremo altri aspetti di questa versione moderna del Javascript, lo approfondiremo per impiegarlo poi in contesti pi\u00f9 complessi.<\/p>\n<p>Continuate a seguirci!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In un articolo precedente, abbiamo preso confidenza con\u00a0TypeScript, la nuova frontiera del mondo Javascript, che ha introdotto&#8230;<\/p>\n","protected":false},"author":561,"featured_media":12893,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[1538,1537,18,1753],"class_list":["post-12397","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorial-pratici","tag-javascript","tag-node-js","tag-oop","tag-typescript"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12397","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/users\/561"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/comments?post=12397"}],"version-history":[{"count":7,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12397\/revisions"}],"predecessor-version":[{"id":12959,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/posts\/12397\/revisions\/12959"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media\/12893"}],"wp:attachment":[{"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/media?parent=12397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/categories?post=12397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devapp.it\/wordpress\/wp-json\/wp\/v2\/tags?post=12397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}