Programmazione ad oggetti: Cenni generali
Michelangelo Diligenti Ingegneria Informatica e
dell'Informazione
diligmic@diism.unisi.it
Argomenti
●
Programmazione ad oggetti
Motivazioni
Classi
Metodi e membri
Primi cenni di sintassi C++ per realizzare classi
Motivazioni per la
programmazione ad oggetti
●
Riusabilità
Sviluppo di componenti software indipendenti e portabili
Creazione di librerie generiche e facilmente integrabili
●
Estensibilità
Facile prendere il codice ed estenderlo a nuove funzionalità desiderate
●
Flessibilità
Modifiche che siano isolate e non rompano l'intero sistema
Il processo di progettazione
●
Goal: creare un sistema software
●
Decomporre il sistema in componenti indipendenti:
Ripetere in modo iterativo: un componente può essere diviso in sotto-componenti e così via
Processo top-down
●
Astrazione
Non serve conoscere i dettagli del software
Per fare design non penso a come implementare!
●
Design può seguire diversi paradigmi
Procedurale o Modulare
Ad oggetti
Astrazione
●
Definire gli attributi ed i comportamenti delle entità (componenti software), trascurando come queste sono implementate
●
Proprietà
Comprensibile nomi sono intiutivi
Coerente e corretta fa ciò che si desidera
Minima non contiene attributi o comporamenti inutili
Completa contiene tutti gli attributi e comportamenti desiderati
Forme di astrazione
● Procedurale (funzioni)
Definisce funzioni che realizzano il task
Definisce i parametri passati tra le funzioni
Programmazione in C viene spesso fatta con questa modalità
Difficile isolare i componenti, non poca riusabilità e flessibilità
Difficile capire chi cambia cosa e trovare i bugs
● Modulare
Definisce dei moduli con dati e procedure
Ogni modulo ha solo una parte visibile dall'esterno (pubblica)
● Ad oggetti (object-oriented)
Tipi di dati astratti implementati da classi
Ogni progetto è suddiviso in classi
Ogni classe ha definite delle funzionalità pubbliche e private
Un oggetto è un'istanza di una classe
Programmazione ad oggetti
●
Simile al modulare ma con costrutti ben definiti e specifici
– Costruire un sistema partendo dalle sue parti
●
Ogni parte del sistema è un oggetto con
– Attributi o membri o dati: definiscono le sottoparti dell'oggetto. Possono essere
● Altri oggetti
● Tipi elementari come numeri o stringhe
– Metodi: definiscono le operazioni che sono effettuabili su un oggetto
Programmazione ad oggetti
●
Ogni oggetto può essere riusato in altri contesti
●
Possibile usare l'oggetto per quello che fa, non per come è realizzato
Una macchina ci porta dove vogliamo senza sapere esattamente come funziona il suo motore
Solo chi implementa conosce i dettagli
Astrazione: chi utilizza l'oggetto non sa come e' implementato!
●
Implementazione possibile attraverso vari linguaggi
– C++, Java, ecc.
Processo di astrazione e software
entità
attributi
funzionalità
Mondo reale Astrazione software
{data, data,…}
{method, method,…}
Classe
Dati
Metodi
Separazione dell'interfaccia ed implementazione
Interfaccia
Implementazione
visible nascosta
• Interfaccia: Cosa fare
• Implementazione: Come farlo
• Usare l'interfaccia senza sapere nulla dell'implementazione
• Programmazione Contract-based
• Permette l'astrazione
Struttura di una classe
●
Classe
Astrazione di un oggetto che separa l'interfaccia dall'implementazione
●
Una classe rappresenta tutti i membri di un gruppo di oggetti (istanze della classe)
●
Una classe ha un'interfaccia pubblica ed un' implementazione privata
●
Dati ed algoritmi sono privati e quindi nascosti all'utente
Questo evita errate alterazioni dello stato
Programmazione ad oggetti:
esempio
●
Si parte da delle specifiche
●
Spesso importanti dettagli mancano
●
Molto detto non è importante
Specifica:
Progetta un catalogo per la musica, che permetta di aggiungere album, informazioni su artisti ed albums, titoli di canzoni e compositori. Gli utenti devono anche essere in grado di cercare informazioni nella collezione.
Passo 1: identificare gli oggetti
●
Cerchiamo i nomi di cose nelle specifiche
musica
catalogo
utente
canzone
titolo
artista
disco
compositore
informazione
●
Cosa considerare come oggetti da convertire in classi?
Specifiche:
Progetta un catalogo per la musica, che
permetta di aggiungere album, informazioni su artisti ed albums, titoli di canzoni e
compositori. Gli utenti devono anche essere in grado di cercare informazioni nella collezione.
Passo 1: identificare gli oggetti
●
Un oggetto deve:
Essere un entità reale con un chiaro confine
Essere rilevante nelle specifiche
●
Attenzione se
L'oggetto è un azione
L'oggetto astrae due concetti
L'oggetto ha nessuna od una sola azione da compiere
Passo 1: identificare gli oggetti
●
Vediamo i singoli candidati
musica: troppo generale e poco concreto
catalogo: utile e concreto, si accede dall'esterno
utente: entità esterna al sistema, non va modellato ma gli va fornito un modo per fare le sue operazioni sugli oggetti
canzone: utile e rilevante
titolo: non rilevante, attributo di canzone e disco
artista: non rilevante, attributo di disco
disco: utile e chiaro, contiene una lista di oggetti canzone
compositore: non rilevante, attributo di canzone
informazione (troppo generale e non concreto)
Passo 2: identificare i dati
●
Cosa contiene ogni oggetto?
●
Catalogo
Lista di dischi: vector<Disco>
●
Disco
Autore: string
Titolo: string
Lista di canzoni: vector<Canzone>
●
Canzone
Compositore: string
Titolo: string
Passo 3: identificare le funzionalità
●
Catalogo
void AggiungiDisco(Disco disco);
Disco GetDisco(string titolo);
vector<Disco> GetDischi(string autore);
●
Disco
vector<Canzone> GetCanzoni();
string GetTitolo();
●
Canzone
string GetCompositore();
string GetTitolo();
Passo 4: stabilire la visibilità
●
Chi può accedere alle funzionalità di una classe?
Chiunque: metodi detti public
Solo la classe stessa: metodi detti private
Solo alcune classi correlate: metodi detti protected
Solo alcuni metodi o classi specifiche: metodi detti friend
●
Metodi public definiscono l'interfaccia di una classe
Definiscono come la classe viene usata dall'esterno
I metodi sono invocati su un'istanza specifica
Riassumendo
●
Ogni cosa è modellabile come un oggetto
●
Un oggetto ha un tipo: la sua classe
●
Un oggetto è associato a:
Attributi (i dati che definiscono l'oggetto)
Funzioni (chiamati metodi in OOP), definiscono tutti ed i soli modi di usarlo
●
Oggetto ha funzioni con cui lo si usa dall'esterno
Insieme di metodi pubblici formano l'interfaccia
●
Data una classe si costruiscono istanze di essa
Come per un float, vi sono infinite possibili istanze di
Esempio di classi e visibilità
class Point { private:
float x;
float y;
public:
float Dist(const Point& pt);
};
class Rectangle { private:
Point anchor;
float width, height;
public:
float Area();
float Perimeter();
Point Center();
};
Dati (attributi) Metodi (funzionalità)
Dati (attributi) Metodi (funzionalità)
OOP in C++: primi concetti
●
Definizione di classe
class NomeClasse {
… };
●
Inizio dati o metodi privati
private:
●
Inizio dati o metodi pubblici
public:
●
Dato (come qualsiasi dato in C)
[float, double, int, AltroNomeClasse…] nomeDato;
●
Metodo (simile a funzioni in C)
OOP in C++: esempio
class Serbatoio { private:
int livello;
public:
int Livello() { return livello; }
void Riempire(int delta_livello) { livello += delta_livello;
}
void Svuotare(int delta_livello) { livello -= delta_livello;
} };
Un metodo permette accedere allo stato senza modificarlo
Metodi definiscono come usare la classe. I dati privati sono disponibili nel metodo senza passarli come argomento
Buona norma avere i dati privati.
Permette di evitare
che qualcuno modifichi lo stato della classe.
OOP in C++: note
● Un metodo di una class C viene applicat ad un'istanza:
– tutti i dati di C sono visibili (anche i privati)
● non necessario passarli
– possibile chiamare i metodi pubblici o privati di C stessa class Serbatoio {
private:
int livello;
public:
void Riempire(int delta_livello) { livello += delta_livello; } void Svuotare(int delta_livello) {
Riempire(-delta_livello);
} };
Chiamo un metodo da un altro metdo
Dato privato è visibile
OOP in C++: costruttori
class Serbatoio { ...
public:
Serbatoio() { livello = 0;
};
Serbatoio(int livello_iniziale) { livello = livello_iniziale;
} };
Esistono dei metodi speciali
che hanno il nome della classe.
Sono detti Costruttori e definiscono le operazioni da fare per costruire un istanza della classe
Vi possono essere più costruttori che prendono diversi parametri.
Il costruttore senza parametri è detto Default Constructor
Se nessun costruttore è definito, il compilatore ne crea uno di default, ma non sempre fa ciò che si desidera!
Buona norma aggiungere i costruttori che si vogliono usare
OOP in C++: uso dei metodi
#include <iostream>
class Serbatoio { ...
};
int main() {
Serbatoio s(5);
s.Riempire(3);
printf(“%d\n”, ”s.Livello());
return 0;
Usare una classe vuol dire
1) definire un istanza e chiamare il costruttore
2) chiamare l'interfaccia come istanza.metodo()
OOP in C++: istanze di classe
#include <iostream>
class Serbatoio { ...
};
int main() {
Serbatoio s1(5);
Serbatoio s2(10);
… }
● Classe: tipo di oggetto
● Istanza: variabile che contiene una singola incarnazione di una classe
Data una class Serbatoio
Possibile instanziare un numero infinito di istanze di serbatoi: s1. s2, ...
Metodi speciali: accessors
●
Dati sempre privati
●
Metodi accessors o getters permettono di
accedere ai dati privati dall'esterno della classe
Sone sempre metodi const, senza parametri
Dati restano protetti in quanto non cambiabili
Esempio
class Serbatoio { private:
std::string nome;
int livello;
public:
int Livello() { return livello; }
const std::string& Nome() { return nome; } std::string Nome() { return nome; }
Ritorna per const reference o per valore
Metodi speciali: setters
●
Dati sempre privati
●
Metodi setters permettono di modificare i dati privati
Non sono const per definizione, accettano un parametro
Vanno definiti solo quando si vuole far cambiare lo stato dall'esterno in modo controllato
Esempio
class Serbatoio { private:
std::string nome;
int livello;
public:
void SetLivello(int livello_) { livello = livello_; }
void SetNome(const std::string& nome_) { nome = nome_; } };
OOP in C++: esercizio
●
Completare la classe Rettangolo e Punto vista in precedenza
Aggiungere costruttori
Implementare i metodi
Aggiungere main che costruisce rettangolo e ne stampa area, perimetro e centro
OOP in C++: esercizio
●
Realizzare del software che permetta di effettuare calcoli con numeri complessi. Deve essere possibile sommare o moltiplicare due numeri complessi.
– Usare la programmazione ad oggetti
– Classe NumeroComplesso
● Stabilire dati membri e metodi da realizzare
● Stabilire la loro visibilità
● Implementare i costruttori che ritenete necessari
● Implementare i metodi
– Nota (a+ib)*(c+id) = (ac -bd) + i(bc+ad)
OOP in C++: esercizio
● PARTE 1
Si deve realizzare una classe che realizza un generatore casuale di numeri interi (usando la funzione rand() come generatore sottostante). Deve essere possibile
inizializzare il generatore con un seme o richiedere un nuovo numero casuale.
Effettuate il design della classe ed implementatelo in C++.
Chiamatela dal main, stampando i primi 100 numeri generati.
● PARTE 2
Come PARTE 1 ma si deve ritornare un float e deve essere possibile specificare il min e max dell'intervallo tra cui i numeri devono stare.
OOP in C++: esercizio
●
PARTE 3
Definire ed implementare una classe che defisce un polinomio di grado 2
y = Ax
2+ Bx + C
La classe deve permettere di inizializzare A,B,C.
La classe deve permettere di calcolare y dato x.
La classe deve permettere di calcolare le radici del polinomio (-B +/- √(B2 – 4AC)/2A)