Skillbook Logo
foto profilo

Skill Factory

Lista post > TypeScript - Lezione 6: Paradigma Object Oriented (prima parte)

TypeScript - Lezione 6: Paradigma Object Oriented (prima parte)

Gino Visciano | Skill Factory - 28/07/2020 23:29:50 | in Tutorials

Il paradigma Object Oriented prevede che le applicazioni siano  composte da un insieme di componenti, chiamti oggetti oppure istanze, che collaborano tra loro per svolgere un lavoro o risolvere un problema.

Il Diagramma di collaborazione seguente mostra un esempio di applicazione Object Oriented.

 

Tutte le applicazioni si possono assemblare utilizzando tre tipi di oggetti: 

- I MODEL sono oggetti che contengono i dati di un entità, corrispondono ai record delle tabelle, permettono di memorizzare temporaneamente i dati in memoria;
- Le 
VIEW sono oggetti oppure viste,  come ad esempio le pagine htmlpermettono la visualizzazione oppure l'inserimento di informazioni;
- I 
CONTROLLER  sono oggetti che hanno il compito di gestire un flusso logico applicativo, all'interno della stessa applicazione ci possono essere anche più CONTROLLER.

L'immagine seguente mostra un diagramma di classe che descrive una classe  che contiene gli attributi di una Persona.

Con una classe di questo tipo è possibile istanziare oggetti di tipo MODEL.

L'immagine seguente mostra il mockup di una pagina.html che permette di inserire i dati che verranno memorizzati in un oggetto di tipo Persona:

L'immagine seguente mostra un diagramma di classe con la classe GestionePersone di tipo CONTROLLER che, attraverso il metodo main, implementa la logica necessaria per gestire oggetti di tipo Persona: 

 

COLLABORAZIONE TRA COMPONENTI

Quando si lavora con un linguaggio ad oggetti bisogna ricordare alcune regole importanti per permettere la collaborazione (comunicazione) tra i componenti dell'applicazione:

1) Una classe diventa un componente (oggetto) quando s'istanzia, solo in questo caso è possibile usare gli attributi ed i metodi pubblici, come mostra il codice TypeScript seguente:

Persona personaUno = new Persona();
Persona personaDue = new Persona();
personaUno.setNome("Pippo");
personaUno.setCognome("Rossi");
personaUno.setEta(35);
personaDue.setNome("Carla");
personaDue.setCognome("Verdi");
personaDue.setEta(30);

L'immagine seguete mostra prima il Diagramma di Classe che descrive la classe Persona, di seguito attraverso un Diagramma ad Oggetti vengono descritti gli stati delle istanze (oggetti) dei due compenenti di tipo MODEL  creati usando la classe Persona.

I due componenti istanziati sono stati allocati in memoria e gli indirizzi (riferimenti) memorizzati nelle variabili personaUno e personaDue di tipo Persona.

2) Gli attributi ed i metodi  pubblici di una classe si definiscono Interfaccia. I componenti possono collaborare (comunicare) tra loro solo attraverso l'interfaccia.  

Ad esempio l'interfaccia della classe Persona è composta solo dai metodi:

public setNome(nome:string):void;
public setCognome(cognome:string):void;
public setEta(eta:number):void;
public getNome():string;
public getCognome():string;
public getEta():int;

perché gli attributi sono tutti privati e non possono essere visibili agli altri componenti.

3) Un componente che usa gli attributi ed i metodi pubblici (interfaccia) di un altro componenete ha il ruolo di Client, l'altro ha il ruolo di Server

L'immagine seguente mostra la classe Prima, di tipo Client, perché attraverso i metodi stampaDivisione() e stampaValore(), utilizza l'attributo valore ed il metodo divisione(...) della classe Seconda, che ha il ruolo di Server.

I metodi di una classe Client per usare gli attributi ed i metodi pubblici (interfaccia) di una classe Server devono istanziarla, come mostra l'esempio seguente:

Esempio 1

 
// prima.ts classe Client
import {Secondafrom './seconda'
export class Prima{
    public stampaDivisione():void{
        //Istanza classe Server
        var seconda:Seconda =new Seconda();
        console.log("Divisione 10/5="+seconda.divisione(10,5));
    }
    public stampaValore():void{
        //Istanza classe Server
        var seconda:Seconda =new Seconda();
        console.log("valore="+seconda.valore);
    }
}
 

 

 
// seconda.ts classe Server
export class Seconda{
    //Interfaccia classe Server perché entrambi gli elementi sono pubblici
    public valore:number=10;
    public divisione(dividendo:number,divisore:number):number{
        return dividendo/divisore;
    }
}
 

 

 
import {Primafrom './prima'
//Istanza classe Prima perché per poter usare 
//i suoi elementi pubblici deve diventare un componente 
var prima:Prima=new Prima();
prima.stampaDivisione();
prima.stampaValore();
 

 

Tra la classe Client Prima e la classe Server Seconda esiste una dipendenza, perché entrambi i metodi stampaDivisione() e stampaValore() di classe Prima istanziano un componente di tipo Seconda.

Quando esiste una dipendenza le classi si dicono accoppiate


PROPRIETA' DEL PARADIGMA OBJECT ORIENTED

Il paradigma Object Oriented prevede tre proprietà di programmazione e due architetturali.

Proprietà di programmazione:

1) Incapsulamento
2) Ereditarietà
3) Polimorfismo

Il Polimorfismo può essere diviso in:

1) Polimorfismo dei metodi: Overload ed Override
2) Polimorfismo degli oggetti, che si può ottenere per ereditarietà oppure per interfaccia.

Le proprietà di programmazione permettono di sviluppare le classi ed impostare le loro caratteristiche ed il loro comportamento

Proprietà architetturali:

1) Coesione
2) Disaccoppiamento

Le proprietà architetturali permettono d'impostare la struttura e l'organizzazione delle applicazioni ad oggetti, per migliorarne le funzionalità e la qualità

 

PROPRIETA' DI PROGRAMMAZIONE DEL PARADIGMA OBJECT ORIENTED

Le proprietà descritte di seguito sono disponibili unicamente nei linguaggio orientatti agli oggetti (Object Oriented),  come ad esempio: C++, C#, Java, TypeScript e Python.

INCAPSULAMENTO

L'incapsulamento, attraverso i modificatori di accesso,  permette di regolare la visibilità e quindi l'utilizzo degli elementi di una classe:

- Attributi
- Metodi
- Costruttori

da parte dei metodi di altre classi.

I modificatori di accesso disponbili in TypeScript sono:

- public         (+, notazione UML)
- private        (-, notazione UML)
- protected  (#, notazione UML)

a)  un elemento è public è visibile a tutti i metodi sia della classe a cui appartiene, sia ai metodi di altre classi.
b)  un elemento è private è visibile solo a tutti i metodi della classe a cui appartiene, ma non è visibile ai metodi di altre classi.
c)  un elemento è protected è visibile solo a tutti i metodi della classe a cui appartiene ed a quelli delle classi che ereditano la classe che contiene l'elemento protected, ma non è visibile ai metodi di altre classi.

 


Esempio 2

 
// incapsulamento.rs
class Test{
public a:number=10;
private b:number=20;
protected c:number=30;
}
class TestA{
public eseguiTest(){
     // Verifica incapsulamento per istanza (dipendenza)
     var test:Test=new Test();
     console.log("a="+test.a+" (public)")
     console.log("b=non visibile (private)");
     console.log("c=non visibile (protected)");
}
}
class TestB extends Test{
    public eseguiTest(){
         // Verifica incapsulamento per ereditarietà
         console.log("a="+this.a+" (public)")
         console.log("b=non visibile (private)");
         console.log("c="+this.c+" (protected)");
    }
    }
 
// Controller
class Main{
    public static main(){
        var testA:TestA=new TestA();
        var testB:TestB=new TestB();
        console.log("----- Test incapsulamento per dipendenza -----")
        testA.eseguiTest();
        console.log("----- Test incapsulamento per ereditarietà -----")
        testB.eseguiTest();
    }
}
 
//main
Main.main();
 
----------------------------------------------------------------------------
----- Test incapsulamento per dipendenza -----
a=10 (public)
b=non visibile (private)
c=non visibile (protected)
----- Test incapsulamento per ereditarietà -----
a=10 (public)
b=non visibile (private)
c=30 (protected)
 

 

EREDITARIETA'

L'Ereditarietà è una tecnica di riuso del codice, questa proprietà permette di creare una nuova classe, ereditando tutti gli elementi public e protected di un'altra classe, chiamata classe padre.
La classe figlia o derivata può contenere nuovi elementi che permettono di specializzare la classe Padre ereditata

L'Ereditarietà è quasi sempre singola, ovvero una classe figlia può ereditare una sola classe per volta, l'unico linguaggio che permette l'ereditarietà multipla è il C++.

 

EREDITARIETA': REGOLA DEL COSTRUTTORE PARAMETRIZZATO

In caso di ereditarietà, se nella classe padre è presente un costruttore parametrizzato, i suoi argomenti devono essere alimentati dal costruttore della classe figlia, con il metodo super(...), come mostra l'immagine seguente:
 

 

POLIMORFISMO DEI METODI

- OVERLOAD

L'Overload è la proprietà dell'Object Oriented che permette di usare nella stessa classe metodi con lo stesso nome, ma firma diversa.

La firma di un metodo è composta dal nome del metodo più i tipi degli argomenti passati, come mostra l'immagine seguente:

Nella stessa classe possono essere presenti più costruttori con lo stesso nome grazie all'overload, come mostra l'esempio seguente:

Persona() // Costruttore dei default
Persona(nome:string,cognome:string,eta:int) // Costruttore parametrizzato

Firma 1=Persona
Firma 2=Persona+string+string+int

Esempio 3

L'esempio seguente mostra la classe Colori con tre metodi con lo stesso nome, ma firma diversa:
1) colora+string, questo metodo fornisce in output il nome del colore fornito in input come argomento;
2) colora+number, questo metodo fornisce in output il colore corrispondente al progressivo numerico fornito in input come argomento;
3) colora+number+number+number, questo metodo fornisce in output il codice esadecimale del colore corrispondente al codice R,G,B (RED=decimale,GREEN=decimale,BLUE=decimale) fornito in input come argomento.
 

Attenzione in TypeScript l'overload si gestisce con una funzione con argomenti opzionali e l'uso d'interfacce che permettono di definire le firme consentite, come mostra il codice seguente:

 
class Colori {
    public colora(valoreUno:string):string;
    public colora(valoreUno:number):string;
    public colora(valoreUno:number,valoreDue:number,valoreTre:number):string;
    public colora(valoreUno:string | number,valoreDue?:number,valoreTre?:number):string{
    if(arguments.length==3){
        return  "#"+valoreUno.toString(16)+valoreDue.toString(16)+valoreTre.toString(16);
    } else{
        if (typeof valoreUno=="number") {
            switch(valoreUno){
                case 1:
                    return "rosso";
                    break;
                case 2:
                    return "verde";
                    break;
                case 3:
                    return "bianco";
                    break;
                default:
                    return "nero";
                    break;
            }
 
        } else{
            return valoreUno;
        }   
    }
  }
// Controller
class Main{
    public static main():void{
var colori:Colori=new Colori();
console.log(colori.colora("rosso"));
console.log(colori.colora(2));
console.log(colori.colora(200,100,255));
    }
}
// main
Main.main();
 
 
--------------------------------------------------
rosso
verde
#c864ff
 

 

- OVERRIDE

L'Override è la seconda proprietà del polimorfismo dei metodi, serve per cambiare il comportamento di un metodo ereditato dalla classe Padre, come mostra l'esempio seguente:

Esempio 4

Se la classe ChiSeiSeconda eredita la classe ChiSeiPrima, il comportamento del metodo toString() è lo stesso, sia per un oggetto di tipo ChiSeiPrima, sia per un oggetto di tipo ChiSeiSeconda.

 
class ChiSeiPrima {
    public toString():string{
           return "Sono la classe ChiSeiPrima!" ;
    }
}
class ChiSeiSeconda extends ChiSeiPrima{
}
// Controller
class Main{
    public static main():void{
        var chiSeiPrima=new ChiSeiPrima();
        var chiSeiSeconda=new ChiSeiSeconda();
        console.log(chiSeiPrima.toString());
        console.log(chiSeiSeconda.toString());
    }
}
// main
Main.main();
 
------------------------------------------
Sono la classe ChiSeiPrima!
Sono la classe ChiSeiPrima!
 

 

Esempio 5

Se sovrascrivete (override) il metodo  toString() nella classe ChiSeiSeconda, allora il comportamento del metodo sarà diveso se l'oggetto è di tipo ChiSeiPrima oppure di tipo ChiSeiSeconda.

 
class ChiSeiPrima {
    public toString():string{
           return "Sono la classe ChiSeiPrima!" ;
    }
}
class ChiSeiSeconda extends ChiSeiPrima{
    //Override
    public toString():string{
        return "Sono la classe ChiSeiSeconda!" ;
 }
}
// Controller
class Main{
    public static main():void{
        var chiSeiPrima=new ChiSeiPrima();
        var chiSeiSeconda=new ChiSeiSeconda();
        console.log(chiSeiPrima.toString());
        console.log(chiSeiSeconda.toString());
    }
}
 
----------------------------------------------
Sono la classe ChiSeiPrima!
Sono la classe ChiSeiSeconda!
 
 

 

- OVERRIDE: OPERATORE SUPER

Quando si sovrascrive (override) un metodo in una classe figlia, per poter utilizzare lo stesso metodo della classe Padre, dovete usare l'operatore super

Ricordate che quando istanziate un oggetto utilizzando una classe, l'operatore this diventerà il riferimento dell'oggetto creato, mentre super diventerà il riferimento dell'oggetto padre. 

 
class ChiSeiPrima {
    public toString():string{
           return "Sono la classe ChiSeiPrima!" ;
    }
}
class ChiSeiSeconda extends ChiSeiPrima{
    //Override
    public toString():string{
        return super.toString()+", Sono la classe ChiSeiSeconda!" ;
 }
}
// main
var chiSeiPrima=new ChiSeiPrima();
var chiSeiSeconda=new ChiSeiSeconda();
console.log(chiSeiPrima.toString());
console.log(chiSeiSeconda.toString());
 
-----------------------------------------------
Sono la classe ChiSeiPrima!
Sono la classe ChiSeiPrima!, Sono la classe ChiSeiSeconda!
 

 

Continua nella prossima lezione dove vedremo il Polimorfismo degli oggetti e le proprietà architetturali del paradigma Object Oriented.


<< Lezione precedente           Lezione successiva >> | Vai alla prima lezione


T U T O R I A L S    S U G G E R I T I


EDUCATIONAL GAMING BOOK (EGB) "H2O"

Nell'era dello SMART LEARNING e di PYTHON i libri non si scrivono, ma si sviluppano, in questo modo chi studia, può sperimentare ed apprendere contemporaneamente; un libro con queste caratteristiche lo possiamo definire un  Educational Gaming Book (EGB).

"H2Oè un EGB che descrive tutte le caratteristiche dell'acqua, la sostanza formata da molecole di H2O, che attraverso il suo ciclo di vita garantisce la sopravvivenza di tutti gli esseri viventi del Pianeta

L'obiettivo dell'EGB è quello di far conoscere ai giovani le proprietà dell'acqua, sotto molti aspetti uniche, per sensibilizzarli a salvaguardare un bene comune raro, indispensabile per la vita


Per il DOWNLOAD di "H2Oclicca qui.

Share Button
TOP