introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è...

9
1 Introduzione alla programmazione orientata agli oggetti (prima parte) Rel 1.0 a cura del prof. Francesco Tappi Il paradigma orientato agli oggetti implica lo sviluppo di unità di programmazione attive, chiamate oggetti, ognuna delle quali contiene procedure che descrivono il modo in cui l’oggetto reagisce a vari stimoli. L’approccio di tipo object-oriented a un problema consiste nell’identificare gli oggetti coinvolti e nel descriverli come unità autonome. Cos’è un Oggetto? Prendete la definizione da vocabolario: “Un oggetto è un’entità che si possa immaginare dotata di determinate caratteristiche e funzionalità”. Il confinamento di informazioni e funzionalità in oggetti permette livelli maggiori di astrazione e semplifica la gestione di sistemi complessi. Gli oggetti nel software possono rappresentare entità del mondo reale: il primo uso di linguaggi a oggetti è stato fatto per effettuare simulazioni. Classi e oggetti Considerate il processo di sviluppo di un videogioco in cui il giocatore deve proteggere la Terra dall’invasione degli orchi combattendo con alcuni soldati. Ogni volta che un soldato attacca, consuma la sua limitata sorgente di energia interna. Semplificando il più possibile il problema, ogni soldato si muove solamente lungo una linea orizzontale. Ogni soldato dovrebbe essere in grado di rispondere ai comandi per muoversi a destra, a sinistra e per combattere.

Upload: others

Post on 21-Feb-2021

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

1

Introduzione alla programmazione orientata agli oggetti (prima parte) Rel 1.0

a cura del prof. Francesco Tappi

Il paradigma orientato agli oggetti implica lo sviluppo di unità di programmazione attive, chiamate oggetti, ognuna delle quali contiene procedure che descrivono il modo in cui l’oggetto reagisce a vari stimoli. L’approccio di tipo object-oriented a un problema consiste nell’identificare gli oggetti coinvolti e nel descriverli come unità autonome.

Cos’è un Oggetto?

Prendete la definizione da vocabolario: “Un oggetto è un’entità che si possa immaginare dotata di determinate caratteristiche e funzionalità”.

Il confinamento di informazioni e funzionalità in oggetti permette livelli maggiori di astrazione e semplifica la gestione di sistemi complessi.

Gli oggetti nel software possono rappresentare entità del mondo reale: il primo uso di linguaggi a oggetti è stato fatto per effettuare simulazioni.

Classi e oggetti

Considerate il processo di sviluppo di un videogioco in cui il giocatore deve proteggere la Terra dall’invasione degli orchi combattendo con alcuni soldati. Ogni volta che un soldato attacca, consuma la sua limitata sorgente di energia interna. Semplificando il più possibile il problema, ogni soldato si muove solamente lungo una linea orizzontale. Ogni soldato dovrebbe essere in grado di rispondere ai comandi per muoversi a destra, a sinistra e per combattere.

Page 2: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

2

Nel paradigma orientato agli oggetti ogni soldato è realizzato come un oggetto che contiene il valore dell’energia rimasta, la posizione sulla linea orizzontale e anche le procedure per modificare la posizione e combattere. Poiché tutti i soldati hanno le stesse proprietà, possono essere creati dallo stesso modello. Tale modello prende il nome di classe.

Rappresentiamo quindi la classe Soldato, utilizzando il linguaggio C++:

class Soldato { //Variabili di istanza o “attributi della classe” int EnergiaRimasta; int posizione; //Metodi o “funzionalità della classe” void muoviSx( )

{ …}; void muoviDx( )

{ …}; void attacca( )

{…}; }

La classe è costituita da due dichiarazione di variabili intere, EnergiaRimasta e posizione, e tre procedure, muoviSx, muoviDx e attacca, che descrivono i passi da eseguire per ottenere l’azione corrispondente. Qualsiasi oggetto costruito da questo modello avrà le seguenti caratteristiche: due variabili, denominate EnergiaRimasta e posizione, e tre procedure, denominate muoviSx, muoviDx e attacca.

Una variabile che si trova all’interno di un oggetto è chiamata variabile di istanza, mentre le procedure all’interno di un oggetto son chiamate metodi (oppure funzioni membro nel gergo C++). Come si può notare, le dichiarazioni delle variabili d’istanza e le descrizioni dei metodi sono concetti di programmazione procedurale.

Una volta descritta la classe Soldato nel programma (nel main per esempio) possiamo dichiarare che le tre variabili Soldato1, Soldato2, Soldato3 sono di “tipo” Soldato tramite un’istruzione di questo formato

Soldato Soldato1,Soldato2,Soldato3;

Si noti che questo è lo stesso formato dell’istruzione

int x,y,z;

che si usa per creare tre variabili denominate x, y, z di tipo intero.

Page 3: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

3

In C++ l’istruzione Soldato Soldato1; dichiara la variabile Soldato1 di “tipo” Soldato e crea anche un nuovo oggetto usando il modello Soldato e assegna l’oggetto come valore iniziale di Soldato1.

E’ opportuno quindi sottolineare la distinzione tra classi e oggetti.

Una classe è un modello a partire dal quale vengono creati gli oggetti e può essere usata per crearne più d’uno (es. la classe Soldato).

Un oggetto è un’istanza della classe da cui è stato costruito. Nel nostro videogioco Soldato1, Soldato2, Soldato3 sono oggetti (cioè istanze) della classe Soldato.

Possiamo continuare il programma scrivendo istruzioni imperative per dare dei valori precisi alle variabili d’istanza e per attivare i metodi opportuni negli oggetti.

Esempio:

Soldato S1,S2,S3;

S1.EnergiaRimasta = 100;

S1.posizione = 0;

S1.muoviDx( );

S2.EnergiaRimasta = 90;

S2.posizione = 10;

S2.attacca( );

Page 4: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

4

Costruttori

Dopo aver creato un oggetto spesso è necessario eseguire alcune attività iniziali. Per esempio nel nostro videogioco potremmo dare ai diversi laser differenti impostazioni di energia iniziale, il che significa che le variabili d’istanza all’interno dei vari oggetti, denominate EnergiaRimasta e posizione, dovrebbero avere valori di partenza diversi. Queste esigenze sono gestite definendo metodi speciali, chiamati costruttori, che vengono eseguiti automaticamente quando un oggetto viene creato. Il costruttore ha lo stesso nome della classe.

Nel nostro videogioco contempliamo due esigenze: 1. poter dare ad energia e posizione due valori iniziali ben precisi. 2. poter dare ad energia un valore preciso mentre di default il valore della posizione

viene settato a zero. Estendiamo quindi la classe Soldato aggiungendo due costruttori:

class Soldato { //Variabili di istanza o “attributi della classe” int EnergiaRimasta; int posizione;

//Costruttori // Assegna un valore a EnergiaRimasta ed un valore a posizione quando viene creato // un oggetto Soldato(int e, int p) { EnergiaRimasta = e; posizione = p;

} // Assegna un valore a EnergiaRimasta ed il valore di default a posizione quando // viene creato un oggetto

Soldato(int e) { EnergiaRimasta = e; posizione = 0; // 0: valore di default

} //Metodi o “funzionalità della classe” void muoviSx( )

{ …}; void muoviDx( )

{ …}; void attacca( )

{…}; }

Page 5: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

5

Il costruttore assegna alle variabili d’istanza i valori che riceve come parametri. Perciò in base alla definizione della classe, il programmatore C++ dovrà scrivere

Soldato S1(100), S2(90,10), S3(100,15);

S1.muoviDx( );

S2.attacca( );

S3.muoviSx( );

Caratteristiche aggiuntive

Supponiamo ora di voler arricchire il gioco in modo che un giocatore che raggiunge un certo punteggio sia premiato con la “rinascita” di alcuni soldati, che vengono riportati alla loro potenza originale. Tali soldati avranno le stesse proprietà degli altri , ma saranno “immortali”.

Per descrivere oggetti con caratteristiche simili ma differenti, la maggior parte dei linguaggi consentono ad una classe di includere le proprietà di un’altra attraverso l’ereditarietà.

L’ereditarietà si indica in questo modo

class SoldatoImmortale : Soldato { . . . void ricarica( ) { … } }

I due punti (“:”) indicano che questa classe eredita le caratteristiche della classe Soldato, oltre a contenere altre funzionalità, come ad esempio il metodo ricarica che descriverà i passi necessari per reimpostare la variabile d’istanza EnergiaRimasta al suo valore originale.

Il programmatore C++ dovrà scrivere

Soldato S1(100), S2(90,10); SoldatoImmortale S3(90), S4(80,5); S1.muoviDx( ); S4.attacca( ); S3.muoviSx( ); S4.ricarica( );

S1.ricarica( ); // non è lecita perché S1 è di classe Soldato ma non di classe // SoldatoImmortale

Page 6: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

6

A questo punto si vogliano definire alcune categorie speciali di soldati non immortali: arciere, fante e cavaliere.

Tutti i soldati devono capire il messaggio attacca. Il messaggio ha conseguenze diverse a seconda del tipo di soldato:

– un arciere scaglia una freccia – un fante colpisce di spada – un cavaliere lancia una lancia

Il giocatore/computer deve gestire una lista di soldati e poter chiedere ad ogni soldato di attaccare indipendentemente dal tipo ma basandosi solo sulla posizione.

Volendo gestire questo problema utilizzando la programmazione procedurale, avremmo un codice un po’ “rigido” come il seguente:

// esempio di codice rigido!

void attacca(Soldato tipo) {

if ( tipo == arciere ) scagliaLaFreccia();

else if ( tipo == fante ) colpisciDiSpada();

else if ( tipo == cavaliere ) lanciaLaLancia();

}

Che succede se devo aggiungere nuovi tipo di soldato?

Page 7: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

7

Affrontando il problema dal punto di vista della programmazione ad oggetti, possiamo andare a scrivere tre nuove classi, denominate Arciere, Fante, Cavaliere, che ereditano da Soldato ed andare a riscrivere i passi del metodo attacca. Questa riscrittura è nota come override.

class Arciere : Soldato { . . void attacca( ) { //scaglia la freccia } }

class Fante : Soldato { . . void attacca( ) { //colpisce di spada } }

class Cavaliere : Soldato { . . void attacca( ) { //lancia la lancia } }

Il codice per gestire l’attacco diventa più flessibile:

Arciere a;

Cavaliere c;

a.attacca( );

c.attacca( );

Se devo aggiungere un nuovo tipo di soldato, aggiungo la classe corrispondente ma non devo andare a modificare il codice già scritto.

L’interpretazione personalizzata del messaggio “attacca” è una caratteristica peculiare della programmazione ad oggetti ed è nota come polimorfismo.

Un’altra caratteristica associata alla programmazione ad oggetti è l’incapsulamento, che limita l’accesso alle proprietà interne di un oggetto. Dire che alcune funzionalità di un oggetto sono incapsulate significa dire che è in grado di accedervi unicamente l’oggetto stesso. Le

Page 8: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

8

funzionalità incapsulate sono denominate private, quelle accessibili dall’esterno sono dette pubbliche.

Tornando alla classe Soldato, decidiamo che le variabili d’istanza, EnergiaRimasta e posizione, debbano essere modificate solo da metodi interni dell’istanza, nessun’altra unità del programma dovrebbe essere in grado di accedere a questi valori direttamente. Per fare questo dobbiamo rendere private le due variabili d’istanza.

class Soldato { //Variabili di istanza o “attributi della classe” private int EnergiaRimasta; private int posizione;

//Costruttori // Assegna un valore a EnergiaRimasta ed un valore a posizione quando viene creato // un oggetto public Soldato(int e, int p) { EnergiaRimasta = e; posizione = p;

} // Assegna un valore a EnergiaRimasta ed il valore di default a posizione quando // viene creato un oggetto

public Soldato(int e) { EnergiaRimasta = e; posizione = 0;

} //Metodi o “funzionalità della classe” public void muoviSx( )

{ posizione--; //da qui posso accedere a posizione, nonostante sia private };

public void muoviDx( ) { …};

public void attacca( ) { EnergiaRimasta = EnergiaRimasta – 10; };

}

Quando si utilizza la classe Soldato dal main oppure da un’altra unità del programma, esterna alla classe, il programmatore C++ scrive

Soldato s;

Page 9: Introduzione alla programmazione orientata agli oggetti …...della programmazione ad oggetti ed è nota come polimorfismo. Un’altra caratteristica associata alla programmazione

9

s.attacca( ); //OK

s.muoviDx( ); //OK

s.EnergiaRimasta( ); //NON è lecita perché la variabile è definita come private

s.posizione( ); //NON è lecita perché la variabile è definita come private