KEMBAR78
Object Oriented JavaScript con TypeScript | PDF
TypeScript
Object Oriented
Enrico è un nostro amico hi-tech e vuole creare un portale web dove vuole simulare il
funzionamento degli orologi della sua collezione
Sappiamo che web = js
Facendo qualche ricerca veniamo a conoscenza di TypeScript
JavaScript è un linguaggio interpretato di scripting risalente agli anni ‘90 quando i
primi browser grafici si sono diffusi.
Assieme ad HTML e CSS forma la tripletta standard da conoscere se si sviluppa
front-end
è un linguaggio progettato per essere semplice e flessibile per un programmatore alle
prime armi
Queste caratteristiche lo hanno portato ad essere molto diffuso e allo stesso tempo
poco affidabile in progetti di ampia scala e molto criticato
… e oggetto di svariati meme
TypeScript è un superset di JavaScript
valido JS → valido TS
Microsoft
Prima release di TypeScript (0.8) nel 2012, v1.0 nel 2014
TypeScript estende JavaScript con caratteristiche che rendono più strutturata la
scrittura di codice JS
Enrico ci dice che ha una serie di orologi che vuole far vedere sul suo sito.
Di ogni orologio vuole simularne il quadrante.
JavaScript ha una concezione di oggetto tutta sua...
orologio.ts
let orologio = {
setOra(ore : number, minuti : number, secondi : number) : void {
[...]
},
avvia() {
[...]
},
mostraOra() {
[...]
},
aggiornaOra() {
[...]
}
}
In TypeScript, mantenendo la concezione di oggetto di JavaScript, un orologio lo
scriveremmo così.
Vediamo brevemente il funzionamento…
orologio.ts
let orologio = {
setOra(ore : number, minuti : number, secondi : number) : void {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log(this.ore + ":" + this.minuti + ":" + this.secondi)
},
aggiornaOra() { [...] }
}
aggiornaOra() semplicemente aggiunge un secondo e rimodula ore e minuti se
necessario.
Ma cosa c’è esclusivo di TS in questo codice?
orologio.ts
let orologio = {
setOra(ore : number, minuti : number, secondi : number) : void {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log(this.ore + ":" + this.minuti + ":" + this.secondi)
},
aggiornaOra() { [...] }
}
Solamente la tipizzazione nella funzione
E la tipizzazione implicita per le altre variabili
orologio.js
let orologio = {
setOra(ore, minuti, secondi) {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log(this.ore + ":" + this.minuti + ":" + this.secondi)
},
aggiornaOra() { [...] }
}
Tolta la tipizzazione, abbiamo javascript valido.
Ma non il JS che probabilmente conosciamo tutti, bensì la versione 6 di EcmaScript.
ECMAScript
ECMAScript è lo standard che specifica JavaScript
è uno standard ISO, ci sono altre implementazioni (JScript, ActionScript)
ECMA = European Computer Manufacturers Association
A livello pratico, spesso quando si parla di ECMAScript, si sta parlando di JavaScript
JS, ES, TS…. ??
Cerchiamo un attimo di capirci meglio...
Nel 2015 è stato rilasciato EcmaScript 6, che ha portato parecchi cambiamenti nel
linguaggio.
orologio.js
let orologio = {
setOra(ore, minuti, secondi) {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log(this.ore + ":" + this.minuti + ":" + this.secondi)
},
aggiornaOra() { [...] }
}
I primi li abbiamo visti nell’oggetto orologio:
orologio.js
let orologio = {
setOra(ore, minuti, secondi) {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log(this.ore + ":" + this.minuti + ":" + this.secondi)
},
aggiornaOra() { ... }
}
- let (e const)
- arrow functions
A cosa servono?
ES6 - let e const
const ora = new Date()
ora = new Date()
console.log(ora)
let = variabile
const = costante
const ora = new Date()
ora = new Date()
console.log(ora)
ES6 - let e const
Se si riassegna il valore di una costante, si ha un errore!
ES6 - Arrow Functions
let orologio = {
[...]
avvia() {
setInterval( function() {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
[...]
}
orologio.avvia()
Se provassimo ad avviare questo codice...
ES6 - Arrow Functions
let orologio = {
[...]
avvia() {
setInterval( function() {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
[...]
}
orologio.avvia()
...avremmo un errore, perché le funzioni classiche di javascript prendono il contesto
del chiamante al runtime.
Quindi this in questo caso si riferisce al contesto globale e non all’orologio dove è
definito!
Le arrow functions mantengono, invece, il contesto dove sono definite.
Popolarità di ES6 nel tempo
ES6 è ormai disponibile su quasi tutti i maggiori browser (... no Internet Explorer)
Quindi la sua popolarità tra gli sviluppatori è molto alta (quelli attivi nella comunità)
(fonte: https://2018.stateofjs.com/)
let ore : number
ore = 9
console.log(ore)
TypeScript script
Possiamo quindi dire che TS è un superset di ES6
let ore : number
ore = 9
console.log(ore)
TypeScript script
Però nessun browser capisce TypeScript, quindi bisogna compilare.
TYPESCRIPT COMPILER
Dobbiamo passare a JavaScript.
Per farlo si usa tsc.
orologio.ts
let orologio = {
setOra(ore : number, minuti : number, secondi : number) : void {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log(this.ore + ":" + this.minuti + ":" + this.secondi)
},
aggiornaOra() { [...] }
}
Abbiamo il nostro orologio accessoriato.
Lo compiliamo...
tsc orologio.ts
var orologio = {
setOra: function (ore, minuti, secondi) {
this.ore = ore;
this.minuti = minuti;
this.secondi = secondi;
},
avvia: function () {
var _this = this;
setInterval(function () {
_this.aggiornaOra();
_this.mostraOra();
}, 1000);
},
mostraOra: function () {
console.log(this.ore + ":" + this.minuti + ":" + this.secondi);
},
aggiornaOra: function () { [...] }
};
Eccolo qua senza accessori
tsc orologio.ts vs orologio.js
var orologio = {
setOra: function (ore, minuti, secondi) {
this.ore = ore;
this.minuti = minuti;
this.secondi = secondi;
},
avvia: function () {
var _this = this;
setInterval(function () {
_this.aggiornaOra();
_this.mostraOra();
}, 1000);
},
mostraOra: function () {
console.log([...]);
},
aggiornaOra: function () { … }
};
let orologio = {
setOra(ore, minuti, secondi) {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log([...])
},
aggiornaOra() { ... }
}
Ma il risultato non toglie solo la tipizzazione.
tsc orologio.ts vs orologio.js
var orologio = {
setOra: function (ore, minuti, secondi) {
this.ore = ore;
this.minuti = minuti;
this.secondi = secondi;
},
avvia: function () {
var _this = this;
setInterval(function () {
_this.aggiornaOra();
_this.mostraOra();
}, 1000);
},
mostraOra: function () {
console.log([...]);
},
aggiornaOra: function () { … }
};
let orologio = {
setOra(ore, minuti, secondi) {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log([...])
},
aggiornaOra() { ... }
}
Vediamo quali sono le differenze...
tsc orologio.ts vs orologio.js
var orologio = {
setOra: function (ore, minuti, secondi) {
this.ore = ore;
this.minuti = minuti;
this.secondi = secondi;
},
avvia: function () {
var _this = this;
setInterval(function () {
_this.aggiornaOra();
_this.mostraOra();
}, 1000);
},
mostraOra: function () {
console.log([...]);
},
aggiornaOra: function () { … }
};
let orologio = {
setOra(ore, minuti, secondi) {
this.ore = ore
this.minuti = minuti
this.secondi = secondi
},
avvia() {
setInterval( () => {
this.aggiornaOra()
this.mostraOra()
}, 1000)
},
mostraOra() {
console.log([...])
},
aggiornaOra() { ... }
}
var vs let
metodi: function() vs metodi()
_this = this vs this → abbiamo già visto prima!
Perché?
tsc compila a ES3 (1999!)
TYPE HANDLING
Un aiuto per il programmatore - ordine
sotto sotto è tutto mischiato comunque
Cosa c’entra tutto questo con OO?
Torniamo a Enrico: il nostro orologio ha un comportamento interno e un’identità
Forse starebbe bene come TDA?
ES5 non ha il concetto di classe, come si faceva?
CAMBIA - TDA in ES5
function Orologio() {
this.ora = new Ora(new Date())
this.getOra = function() {
return this.ora
}
this.setOra = function(ora) {
this.ora = ora
}
this.avvia = function() {[...]}
this.mostraOra = function() {
console.log(this.ora.getOra())
}
}
var unOrologio = new Orologio()
Una semplice funzione e la parola chiave new per il TDA
Enrico l’orologiaio ci dice che ha due tipi di orologi da mostrare.
alcuni Rolex e alcuni SmartWatches
i Rolex sono analogici e hanno il cronometro
gli SmartWatch hanno la capacità di girare alcune applicazioni
Ereditarietà?
Ereditarietà in ES5
function Rolex() {
this.tempoCronometro = 0
this.costruisciLancetta = function(unita) { ...}
this.startCronometro = function() { ... }
this.stopCronometro = function() { ... }
this.resetCronometro = function() { ... }
}
Rolex.prototype = new Orologio()
Rolex.prototype.mostraOra = function(){
let ore = this.ora.getOre() % 12
let minuti = Math.floor(this.ora.getMinuti() / 5)
let lancettaOre = this.costruisciLancetta(ore)
let lancettaMinuti = this.costruisciLancetta(minuti)
console.log(lancettaOre + "n" + lancettaMinuti)
}
Per l’ereditarietà si usa il concetto di prototipo.
Il prototipo da cui Rolex deve partire è un Orologio
In questo caso il Rolex ha un meccanismo di visualizzazione dell’ora analogico
Ereditarietà in ES5
function SmartWatch() {
this.tempoCronometro = 0
this.avviaApplicazione = function(app) {}
}
SmartWatch.prototype = new Orologio()
Mentre lo SmartWatch digitale
PROTOTIPI
Ereditarietà basata su prototipi
Proprietà e comportamento degli oggetti può essere cambiato al runtime perché si
tratta di ereditarietà tra le istanze e non astrazioni.
Niente ereditarietà multipla
Però ES6 ha introdotto l’accessorio “ereditarietà basata su classi”!
Quindi abbiamo a disposizione le classi, senza bisogno di compilare (tranne per IE)
Orologio
class Orologio {
constructor() {
this.ora = new Ora(new Date())
}
getOra() {
return ora
}
setOra(ora) {
this.ora = ora
}
avvia() { … }
mostraOra() {}
}
Abbiamo le classi, scriviamo il padre Orologio
Rolex
class Rolex extends Orologio {
constructor(){
super()
this.tempoCronometro = 0
}
mostraOra() {
let ore = this.ora.getOre() % 12
let minuti = Math.floor(this.ora.getMinuti() / 5)
let lancettaOre = costruisciLancetta(ore)
let lancettaMinuti = costruisciLancetta(minuti)
console.log(lancettaOre + "n" + lancettaMinuti)
}
costruisciLancetta(unita) { ... }
startCronometro(){ ... }
stopCronometro(){ ... }
resetCronometro(){ ... }
}
E semplicemente con extends scriviamo il figlio
SmartWatch
class SmartWatch extends Orologio {
mostraOra() {
let stringaOra = `${this.ora.getOre()}:${this.ora.getMinuti()}:${this.ora.getSecondi()} `
console.log(stringaOra)
}
avviaApplicazione(app) {}
}
Uguale per l’altro figlio
Polimorfismo in TS
let rolex = new Rolex()
let smart = new SmartWatch()
let orologi : Orologio[] = []
orologi[0] = rolex
orologi[1] = smart
orologi.forEach((orologio) => {
orologio.avvia()
})
Abbiamo parlato di ereditarietà, parliamo di polimorfismo
Ne parliamo in TS, perché in JS, non avendo tipizzazione, il polimorfismo ha un
significato più marginale.
funziona!
JS con ES6 sta piano piano cercando di omologarsi all’oo class-based.
Ok, ma quindi perché ci parli di Object Oriented TypeScript se poi non serve
TypeScript per avere un JavaScript Orientato agli Oggetti?
Parliamo nello specifico di TypeScript
Classi astratte in TS
abstract class Orologio {
ora : Ora
schermo : Display
constructor() {
this.ora = new Ora(new Date())
}
getOra() : Ora {
return this.ora
}
setOra(ora : Ora) : void {
this.ora = ora
}
avvia() { … }
mostraOra() : void
}
TS ci lascia definire le classi astratte.
Qualcosa di nuovo qui: dichiarazione di variabili di classe che non c’era in ES6
(non aveva senso in ES6, non essendoci i tipi, non serve dichiarare in anticipo le
variabili)
In più, TS ci lascia anche definire le interfacce
Interfacce in TS
interface Display {
mostra(ora : Ora) : void
}
Si definisce l’interfaccia
Interfacce in TS
class DisplayAnalogico implements Display {
mostra(ora: Ora) : void {
let ore = ora.getOre() % 12
let minuti = Math.floor(ora.getMinuti() / 5)
let lancettaOre = this.costruisciLancetta(ore)
let lancettaMinuti = this.costruisciLancetta(minuti)
console.log(lancettaOre + "n" + lancettaMinuti)
}
costruisciLancetta(unita : number) : string {
let lancetta = ""
for(let i=0; i<12; i++) {
if(i < unita) lancetta += "_"
else lancetta += "."
}
return lancetta
}
}
E si implementa
Non essendoci l’ereditarietà multipla, le interfacce ci permettono di realizzare
qualcosa del genere.
Quindi TS aggiunge classi astratte e interfacce …
… che però non sono nella lista del professore e neanche in quella di Page-Jones
Quindi JS è gia OO?
INCAPSULAMENTO
Abbiamo visto TDA, abbiamo visto ereditarietà e abbiamo visto polimorfismo.
Manca l’incapsulamento.
Scambio Messaggi
var rolex = new Rolex()
var sw = new SmartWatch()
rolex.mostraOra()
sw.mostraOra()
Scambio messaggi..
… facile, anche ES5 ce la fa! (anche ES3)
poi?
Occultamento delle informazioni
let watch= new Rolex()
watch.mostraOra()
console.log(watch.ora)
...information hiding!
Non c’è!
Variabili private in JS
function Orologio() {
var ora = new Ora(new Date())
this.getOra = function() {
return "hello"
}
this.setOra = function(ora) {
this.ora = ora
}
this.mostraOra = function() {
console.log(this.ora.getOra())
}
}
In ES5 possiamo definire delle variabili che si riferiscono solo al contesto della
funzioni.
Sono quindi variabili private..
… e non accessibili alle sottoclassi.
ES6: niente modificatori di accesso
class Orologio {
constructor() {
this.ora = new Ora(new Date())
}
getOra() {
return ora
}
setOra(ora) {
this.ora = ora
}
avvia() { … }
mostraOra() {}
}
ES6, invece, non ha modificatori per le variabili di classe, quindi è tutto pubblico.
ES6 con le classi non ci lascia definire variabili private..
con ES5 si può… ma è un trade-off tra ereditarietà e variabili private
Quindi scelta tra comodità (classi) e incapsulamento…
no!
Le variabili di classe di TS
abstract class Orologio {
protected ora : Ora
protected schermo : Display
constructor(schermo : Display) {
this.ora = new Ora(new Date())
this.schermo = schermo
}
getOra() : Ora {
return this.ora
}
setOra(ora : Ora) : void {
this.ora = ora
}
mostraOra() : void {
this.schermo.mostra(this.ora)
}
}
Ecco cosa ci lascia fare TS!
3 tipi di modificatori:
- private (accessibile solo alla classe)
- protected (accessibile alle sottoclassi)
- public (implicito se non definito)
Occultamento delle informazioni in TS
let watch = new Rolex()
watch.mostraOra()
mostraOra è pubblico, quindi funziona
Occultamento delle informazioni in TS
let watch = new Rolex()
watch.mostraOra()
console.log(watch.ora)
Orologio.ora invece è protected: errore di compilazione!
Quindi TS cosa ci dà in più?
TS è più del typing. è quello che manca a js per essere veramente OO!
TS è un aiuto per il programmatore, non un limite!
PERCHÉ TYPESCRIPT
Discutendo se introdurre molti di questi concetti nella prossima versione di JS
(ES2019 - ES10)
posso andare dal punto a al punto b con js? Sì, ma vuoi mettere farlo con i sedili in
pelle e l’aria condizionata?
demo compilazione con errori
la flessibilità di JS non viene tolta (nel bene e nel male)
Fonti
https://www.typescriptlang.org/
https://developer.mozilla.org/it/docs/Web/JavaScript/Language_Resources
https://www.html.it/pag/48106/principi-oop-in-javascript/
https://pdfs.semanticscholar.org/3fae/f15a108c65fe6c9e7df1a777b427f4475abc.p
df
https://2018.stateofjs.com/

Object Oriented JavaScript con TypeScript

  • 1.
  • 2.
    Enrico è unnostro amico hi-tech e vuole creare un portale web dove vuole simulare il funzionamento degli orologi della sua collezione Sappiamo che web = js Facendo qualche ricerca veniamo a conoscenza di TypeScript
  • 3.
    JavaScript è unlinguaggio interpretato di scripting risalente agli anni ‘90 quando i primi browser grafici si sono diffusi. Assieme ad HTML e CSS forma la tripletta standard da conoscere se si sviluppa front-end è un linguaggio progettato per essere semplice e flessibile per un programmatore alle prime armi Queste caratteristiche lo hanno portato ad essere molto diffuso e allo stesso tempo poco affidabile in progetti di ampia scala e molto criticato
  • 4.
    … e oggettodi svariati meme
  • 5.
    TypeScript è unsuperset di JavaScript valido JS → valido TS Microsoft Prima release di TypeScript (0.8) nel 2012, v1.0 nel 2014 TypeScript estende JavaScript con caratteristiche che rendono più strutturata la scrittura di codice JS
  • 6.
    Enrico ci diceche ha una serie di orologi che vuole far vedere sul suo sito. Di ogni orologio vuole simularne il quadrante. JavaScript ha una concezione di oggetto tutta sua...
  • 7.
    orologio.ts let orologio ={ setOra(ore : number, minuti : number, secondi : number) : void { [...] }, avvia() { [...] }, mostraOra() { [...] }, aggiornaOra() { [...] } } In TypeScript, mantenendo la concezione di oggetto di JavaScript, un orologio lo scriveremmo così. Vediamo brevemente il funzionamento…
  • 8.
    orologio.ts let orologio ={ setOra(ore : number, minuti : number, secondi : number) : void { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log(this.ore + ":" + this.minuti + ":" + this.secondi) }, aggiornaOra() { [...] } } aggiornaOra() semplicemente aggiunge un secondo e rimodula ore e minuti se necessario. Ma cosa c’è esclusivo di TS in questo codice?
  • 9.
    orologio.ts let orologio ={ setOra(ore : number, minuti : number, secondi : number) : void { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log(this.ore + ":" + this.minuti + ":" + this.secondi) }, aggiornaOra() { [...] } } Solamente la tipizzazione nella funzione E la tipizzazione implicita per le altre variabili
  • 10.
    orologio.js let orologio ={ setOra(ore, minuti, secondi) { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log(this.ore + ":" + this.minuti + ":" + this.secondi) }, aggiornaOra() { [...] } } Tolta la tipizzazione, abbiamo javascript valido. Ma non il JS che probabilmente conosciamo tutti, bensì la versione 6 di EcmaScript.
  • 11.
    ECMAScript ECMAScript è lostandard che specifica JavaScript è uno standard ISO, ci sono altre implementazioni (JScript, ActionScript) ECMA = European Computer Manufacturers Association A livello pratico, spesso quando si parla di ECMAScript, si sta parlando di JavaScript
  • 12.
    JS, ES, TS….?? Cerchiamo un attimo di capirci meglio...
  • 13.
    Nel 2015 èstato rilasciato EcmaScript 6, che ha portato parecchi cambiamenti nel linguaggio.
  • 14.
    orologio.js let orologio ={ setOra(ore, minuti, secondi) { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log(this.ore + ":" + this.minuti + ":" + this.secondi) }, aggiornaOra() { [...] } } I primi li abbiamo visti nell’oggetto orologio:
  • 15.
    orologio.js let orologio ={ setOra(ore, minuti, secondi) { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log(this.ore + ":" + this.minuti + ":" + this.secondi) }, aggiornaOra() { ... } } - let (e const) - arrow functions A cosa servono?
  • 16.
    ES6 - lete const const ora = new Date() ora = new Date() console.log(ora) let = variabile const = costante
  • 17.
    const ora =new Date() ora = new Date() console.log(ora) ES6 - let e const Se si riassegna il valore di una costante, si ha un errore!
  • 18.
    ES6 - ArrowFunctions let orologio = { [...] avvia() { setInterval( function() { this.aggiornaOra() this.mostraOra() }, 1000) }, [...] } orologio.avvia() Se provassimo ad avviare questo codice...
  • 19.
    ES6 - ArrowFunctions let orologio = { [...] avvia() { setInterval( function() { this.aggiornaOra() this.mostraOra() }, 1000) }, [...] } orologio.avvia() ...avremmo un errore, perché le funzioni classiche di javascript prendono il contesto del chiamante al runtime. Quindi this in questo caso si riferisce al contesto globale e non all’orologio dove è definito! Le arrow functions mantengono, invece, il contesto dove sono definite.
  • 20.
    Popolarità di ES6nel tempo ES6 è ormai disponibile su quasi tutti i maggiori browser (... no Internet Explorer) Quindi la sua popolarità tra gli sviluppatori è molto alta (quelli attivi nella comunità) (fonte: https://2018.stateofjs.com/)
  • 21.
    let ore :number ore = 9 console.log(ore) TypeScript script Possiamo quindi dire che TS è un superset di ES6
  • 22.
    let ore :number ore = 9 console.log(ore) TypeScript script Però nessun browser capisce TypeScript, quindi bisogna compilare.
  • 23.
    TYPESCRIPT COMPILER Dobbiamo passarea JavaScript. Per farlo si usa tsc.
  • 24.
    orologio.ts let orologio ={ setOra(ore : number, minuti : number, secondi : number) : void { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log(this.ore + ":" + this.minuti + ":" + this.secondi) }, aggiornaOra() { [...] } } Abbiamo il nostro orologio accessoriato. Lo compiliamo...
  • 25.
    tsc orologio.ts var orologio= { setOra: function (ore, minuti, secondi) { this.ore = ore; this.minuti = minuti; this.secondi = secondi; }, avvia: function () { var _this = this; setInterval(function () { _this.aggiornaOra(); _this.mostraOra(); }, 1000); }, mostraOra: function () { console.log(this.ore + ":" + this.minuti + ":" + this.secondi); }, aggiornaOra: function () { [...] } }; Eccolo qua senza accessori
  • 26.
    tsc orologio.ts vsorologio.js var orologio = { setOra: function (ore, minuti, secondi) { this.ore = ore; this.minuti = minuti; this.secondi = secondi; }, avvia: function () { var _this = this; setInterval(function () { _this.aggiornaOra(); _this.mostraOra(); }, 1000); }, mostraOra: function () { console.log([...]); }, aggiornaOra: function () { … } }; let orologio = { setOra(ore, minuti, secondi) { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log([...]) }, aggiornaOra() { ... } } Ma il risultato non toglie solo la tipizzazione.
  • 27.
    tsc orologio.ts vsorologio.js var orologio = { setOra: function (ore, minuti, secondi) { this.ore = ore; this.minuti = minuti; this.secondi = secondi; }, avvia: function () { var _this = this; setInterval(function () { _this.aggiornaOra(); _this.mostraOra(); }, 1000); }, mostraOra: function () { console.log([...]); }, aggiornaOra: function () { … } }; let orologio = { setOra(ore, minuti, secondi) { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log([...]) }, aggiornaOra() { ... } } Vediamo quali sono le differenze...
  • 28.
    tsc orologio.ts vsorologio.js var orologio = { setOra: function (ore, minuti, secondi) { this.ore = ore; this.minuti = minuti; this.secondi = secondi; }, avvia: function () { var _this = this; setInterval(function () { _this.aggiornaOra(); _this.mostraOra(); }, 1000); }, mostraOra: function () { console.log([...]); }, aggiornaOra: function () { … } }; let orologio = { setOra(ore, minuti, secondi) { this.ore = ore this.minuti = minuti this.secondi = secondi }, avvia() { setInterval( () => { this.aggiornaOra() this.mostraOra() }, 1000) }, mostraOra() { console.log([...]) }, aggiornaOra() { ... } } var vs let metodi: function() vs metodi() _this = this vs this → abbiamo già visto prima! Perché? tsc compila a ES3 (1999!)
  • 29.
    TYPE HANDLING Un aiutoper il programmatore - ordine sotto sotto è tutto mischiato comunque
  • 30.
    Cosa c’entra tuttoquesto con OO? Torniamo a Enrico: il nostro orologio ha un comportamento interno e un’identità Forse starebbe bene come TDA?
  • 31.
    ES5 non hail concetto di classe, come si faceva?
  • 32.
    CAMBIA - TDAin ES5 function Orologio() { this.ora = new Ora(new Date()) this.getOra = function() { return this.ora } this.setOra = function(ora) { this.ora = ora } this.avvia = function() {[...]} this.mostraOra = function() { console.log(this.ora.getOra()) } } var unOrologio = new Orologio() Una semplice funzione e la parola chiave new per il TDA
  • 33.
    Enrico l’orologiaio cidice che ha due tipi di orologi da mostrare. alcuni Rolex e alcuni SmartWatches i Rolex sono analogici e hanno il cronometro gli SmartWatch hanno la capacità di girare alcune applicazioni
  • 34.
  • 35.
    Ereditarietà in ES5 functionRolex() { this.tempoCronometro = 0 this.costruisciLancetta = function(unita) { ...} this.startCronometro = function() { ... } this.stopCronometro = function() { ... } this.resetCronometro = function() { ... } } Rolex.prototype = new Orologio() Rolex.prototype.mostraOra = function(){ let ore = this.ora.getOre() % 12 let minuti = Math.floor(this.ora.getMinuti() / 5) let lancettaOre = this.costruisciLancetta(ore) let lancettaMinuti = this.costruisciLancetta(minuti) console.log(lancettaOre + "n" + lancettaMinuti) } Per l’ereditarietà si usa il concetto di prototipo. Il prototipo da cui Rolex deve partire è un Orologio In questo caso il Rolex ha un meccanismo di visualizzazione dell’ora analogico
  • 36.
    Ereditarietà in ES5 functionSmartWatch() { this.tempoCronometro = 0 this.avviaApplicazione = function(app) {} } SmartWatch.prototype = new Orologio() Mentre lo SmartWatch digitale
  • 37.
    PROTOTIPI Ereditarietà basata suprototipi Proprietà e comportamento degli oggetti può essere cambiato al runtime perché si tratta di ereditarietà tra le istanze e non astrazioni. Niente ereditarietà multipla
  • 38.
    Però ES6 haintrodotto l’accessorio “ereditarietà basata su classi”! Quindi abbiamo a disposizione le classi, senza bisogno di compilare (tranne per IE)
  • 39.
    Orologio class Orologio { constructor(){ this.ora = new Ora(new Date()) } getOra() { return ora } setOra(ora) { this.ora = ora } avvia() { … } mostraOra() {} } Abbiamo le classi, scriviamo il padre Orologio
  • 40.
    Rolex class Rolex extendsOrologio { constructor(){ super() this.tempoCronometro = 0 } mostraOra() { let ore = this.ora.getOre() % 12 let minuti = Math.floor(this.ora.getMinuti() / 5) let lancettaOre = costruisciLancetta(ore) let lancettaMinuti = costruisciLancetta(minuti) console.log(lancettaOre + "n" + lancettaMinuti) } costruisciLancetta(unita) { ... } startCronometro(){ ... } stopCronometro(){ ... } resetCronometro(){ ... } } E semplicemente con extends scriviamo il figlio
  • 41.
    SmartWatch class SmartWatch extendsOrologio { mostraOra() { let stringaOra = `${this.ora.getOre()}:${this.ora.getMinuti()}:${this.ora.getSecondi()} ` console.log(stringaOra) } avviaApplicazione(app) {} } Uguale per l’altro figlio
  • 42.
    Polimorfismo in TS letrolex = new Rolex() let smart = new SmartWatch() let orologi : Orologio[] = [] orologi[0] = rolex orologi[1] = smart orologi.forEach((orologio) => { orologio.avvia() }) Abbiamo parlato di ereditarietà, parliamo di polimorfismo Ne parliamo in TS, perché in JS, non avendo tipizzazione, il polimorfismo ha un significato più marginale. funziona!
  • 43.
    JS con ES6sta piano piano cercando di omologarsi all’oo class-based.
  • 44.
    Ok, ma quindiperché ci parli di Object Oriented TypeScript se poi non serve TypeScript per avere un JavaScript Orientato agli Oggetti? Parliamo nello specifico di TypeScript
  • 45.
    Classi astratte inTS abstract class Orologio { ora : Ora schermo : Display constructor() { this.ora = new Ora(new Date()) } getOra() : Ora { return this.ora } setOra(ora : Ora) : void { this.ora = ora } avvia() { … } mostraOra() : void } TS ci lascia definire le classi astratte. Qualcosa di nuovo qui: dichiarazione di variabili di classe che non c’era in ES6 (non aveva senso in ES6, non essendoci i tipi, non serve dichiarare in anticipo le variabili)
  • 46.
    In più, TSci lascia anche definire le interfacce
  • 47.
    Interfacce in TS interfaceDisplay { mostra(ora : Ora) : void } Si definisce l’interfaccia
  • 48.
    Interfacce in TS classDisplayAnalogico implements Display { mostra(ora: Ora) : void { let ore = ora.getOre() % 12 let minuti = Math.floor(ora.getMinuti() / 5) let lancettaOre = this.costruisciLancetta(ore) let lancettaMinuti = this.costruisciLancetta(minuti) console.log(lancettaOre + "n" + lancettaMinuti) } costruisciLancetta(unita : number) : string { let lancetta = "" for(let i=0; i<12; i++) { if(i < unita) lancetta += "_" else lancetta += "." } return lancetta } } E si implementa
  • 49.
    Non essendoci l’ereditarietàmultipla, le interfacce ci permettono di realizzare qualcosa del genere.
  • 50.
    Quindi TS aggiungeclassi astratte e interfacce … … che però non sono nella lista del professore e neanche in quella di Page-Jones Quindi JS è gia OO?
  • 51.
    INCAPSULAMENTO Abbiamo visto TDA,abbiamo visto ereditarietà e abbiamo visto polimorfismo. Manca l’incapsulamento.
  • 52.
    Scambio Messaggi var rolex= new Rolex() var sw = new SmartWatch() rolex.mostraOra() sw.mostraOra() Scambio messaggi.. … facile, anche ES5 ce la fa! (anche ES3) poi?
  • 53.
    Occultamento delle informazioni letwatch= new Rolex() watch.mostraOra() console.log(watch.ora) ...information hiding! Non c’è!
  • 54.
    Variabili private inJS function Orologio() { var ora = new Ora(new Date()) this.getOra = function() { return "hello" } this.setOra = function(ora) { this.ora = ora } this.mostraOra = function() { console.log(this.ora.getOra()) } } In ES5 possiamo definire delle variabili che si riferiscono solo al contesto della funzioni. Sono quindi variabili private.. … e non accessibili alle sottoclassi.
  • 55.
    ES6: niente modificatoridi accesso class Orologio { constructor() { this.ora = new Ora(new Date()) } getOra() { return ora } setOra(ora) { this.ora = ora } avvia() { … } mostraOra() {} } ES6, invece, non ha modificatori per le variabili di classe, quindi è tutto pubblico.
  • 56.
    ES6 con leclassi non ci lascia definire variabili private.. con ES5 si può… ma è un trade-off tra ereditarietà e variabili private Quindi scelta tra comodità (classi) e incapsulamento… no!
  • 57.
    Le variabili diclasse di TS abstract class Orologio { protected ora : Ora protected schermo : Display constructor(schermo : Display) { this.ora = new Ora(new Date()) this.schermo = schermo } getOra() : Ora { return this.ora } setOra(ora : Ora) : void { this.ora = ora } mostraOra() : void { this.schermo.mostra(this.ora) } } Ecco cosa ci lascia fare TS! 3 tipi di modificatori: - private (accessibile solo alla classe) - protected (accessibile alle sottoclassi) - public (implicito se non definito)
  • 58.
    Occultamento delle informazioniin TS let watch = new Rolex() watch.mostraOra() mostraOra è pubblico, quindi funziona
  • 59.
    Occultamento delle informazioniin TS let watch = new Rolex() watch.mostraOra() console.log(watch.ora) Orologio.ora invece è protected: errore di compilazione!
  • 60.
    Quindi TS cosaci dà in più? TS è più del typing. è quello che manca a js per essere veramente OO! TS è un aiuto per il programmatore, non un limite!
  • 61.
    PERCHÉ TYPESCRIPT Discutendo seintrodurre molti di questi concetti nella prossima versione di JS (ES2019 - ES10) posso andare dal punto a al punto b con js? Sì, ma vuoi mettere farlo con i sedili in pelle e l’aria condizionata? demo compilazione con errori la flessibilità di JS non viene tolta (nel bene e nel male)
  • 62.