• Non ci sono risultati.

Astrazioni in C++

N/A
N/A
Protected

Academic year: 2023

Condividi "Astrazioni in C++"

Copied!
25
0
0

Testo completo

(1)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Astrazioni in C++

Fondamenti di informatica

Michele Tomaiuolo

tomamic@ce.unipr.it

http://www.ce.unipr.it/people/tomamic

(2)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Generale e particolare

Possibile definire relazioni tra classi (sotto-insieme,

specializzazione) Ball: classe base

Diversi tipi di palle: classi derivate

Ereditano caratteristiche di Ball

Aggiungono caratteristiche specifiche: casualità del rimbalzo, elasticità dell'urto...

Ball

CrazyBall SoftBall ...

(3)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Principio di sostituibilità

La specializzazione è una relazione di tipo is-a

È sempre possibile usare un oggetto di una classe derivata al posto di un oggetto di una classe base

field->add(new Ball());

// …

field->add(new CrazyBall());

field->add(new SoftBall());

// …

field->moveAll();

field->print();

(4)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Metodi e campi ereditati

Classe derivata, definita a partire da classe base:

Eredita tutte le caratteristiche public della classe base Non ha accesso alla sezione private della classe base Può definire nuove caratteristiche (Eckel: is-like-a)

class CrazyBall : public Ball { // additional features

}

Classe base:

Può definire delle caratteristiche protected , a cui solo

lei e le classi derivate possono accedere

(5)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Polimorfismo

Un metodo polimorfo di una classe base è ridefinibile nelle classi derivate

Un tale metodo deve essere dichiarato virtual nella classe base

Occorre una tabella (vtable) che associ il giusto metodo ad un oggetto a runtime

Inoltre, bisogna usare puntatori

Altrimenti slicing: l'oggetto di classe derivata viene convertito nella classe base!

Es. Rendere move ridefinibile

(6)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

#ifndef BALL_H

#define BALL_H class Ball { public:

static const int WIDTH = 16;

static const int HEIGHT = 12;

Ball();

Ball(int x0, int y0, int dx0, int dy0);

int getX();

int getY();

virtual void move();

protected:

int x; int y;

int dx; int dy;

};

#endif

Metodi virtual

virtual, così può essere ridefinito dalle sotto-classi

virtual, così può essere ridefinito dalle sotto-classi

(7)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

#ifndef CRAZYBALL_H

#define CRAZYBALL_H

#include "ball.h"

class CrazyBall : public Ball { public:

CrazyBall();

CrazyBall(int x, int y, int dx, int dy, int randomness);

void move();

private:

int randomness; // in percent };

#endif

Classe CrazyBall

Ball

CrazyBall

- randomness : int + move() : void

(8)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

#include "crazyball.h"

CrazyBall::CrazyBall() : Ball() { randomness = 0;

}

CrazyBall::CrazyBall(int x, int y, int dx, int dy, int randomness)

: Ball(x, y, dx, dy) {

this->randomness = randomness;

}

void CrazyBall::move() {

if (x+dx < 0 || x+dx >= WIDTH) { dx = -dx;

if ((rand() % 100) < randomness) { dy = rand() % 2 – 1;

// ...

Implementazione

Sezione di inizializzazione dopo i “:” e prima del corpo Sezione di inizializzazione dopo i “:” e prima del corpo

(9)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

#include "ball.h"

#include "crazyball.h"

int main() {

Ball* b1 = new Ball(8, 4, +1, +1);

Ball* b2 = new CrazyBall(4, 8, -1, +1);

b1->move(); // the method of Ball

b2->move(); // the method of CrazyBall!

}

Se move non fosse virtual, sarebbe eseguito

il metodo di Ball Se move non fosse virtual, sarebbe eseguito

il metodo di Ball

Applicazione

(10)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Distruttori virtual e costruttori

In caso di polimorfismo, la classe base deve sempre dichiarare virtual il suo distruttore, altrimenti...

Eseguito sempre e solo il distruttore della classe base Non quello giusto, della classe derivata

Liberate risorse della classe base, non della derivata

I costruttori non vengono ereditati

Non inizializzano gli attributi aggiunti in classe derivata

Ma necessario eseguire costruttore della classe base

Costruire prima le caratteristiche della classe base...

poi quelle della classe derivata

(11)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Sezione di inizializzazione

Precede il corpo di un costruttore

Indicare un costruttore della classe base

(altrimenti, scelto quello senza parametri, se c'è...) Inizializzare gli attributi (più efficiente)

Necessario inizializzare costanti di istanza e oggetti membri (altrimenti costruiti senza parametri...)

Oggetti nello heap: new nel corpo del costruttore

CrazyBall::CrazyBall(int x, int y, int dx, int dy, int r) : Ball(x, y, dx, dy), randomness(r) {

/* intentionally empty*/

}

Sezione di inizializzazione

dopo i “:” e prima del corpo Sezione di inizializzazione dopo i “:” e prima del corpo

(12)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Clausola protected

Per metodi e attributi accessibili solo dalla classe e dalle derivate

Non visibili all’esterno della classe, come se fossero privati

Ma visibili alle sue classi derivate

Da usare con cautela; solo per caratteristiche…

Che non conviene rendere pubbliche:

campi incapsulati, o servizi non significativi

Ma potenzialmente utili a chi estende la classe

(13)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Classe astratta

Contiene alcuni metodi astratti (senza implementazione)

Saranno implementati dalle sue sotto-classi Informazioni non sufficienti nella classe base

Meccanismi specifici per implementare un metodo

Una classe astratta non può essere istanziata

Classe astratta pura, o interfaccia: contiene solo

metodi astratti

(14)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

class MovingObject { public:

virtual void move() = 0;

virtual int getX() = 0;

virtual int getY() = 0;

}

MovingObject

MovingObject

+ getX() : int + getY() : int + move() : void

Stone Ghost Ball

Tutti i metodi sono virtuali puri → La classe

è detta “astratta pura”, o “interfaccia”

Tutti i metodi sono virtuali puri → La classe

è detta “astratta pura”, o “interfaccia”

Se uno dei metodi è virtuale puro → La classe

è “astratta”, non può avere istanze dirette

Se uno dei metodi è virtuale puro → La classe

è “astratta”, non può avere istanze dirette

(15)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

class Ghost : public MovingObject { public:

Ghost(int x, int y,

int width, int height);

int getX();

int getY();

void move();

private:

int x; int y; int width; int height;

}

Ghost::Ghost(int x, int y, int width, int height) {/*…*/}

int Ghost::getX() { return x; } int Ghost::getY() { return y; } void Ghost::move() {

int dx = rand() % 3 – 1; x = (x + dx + width) % width;

int dy = rand() % 3 – 1; y = (y + dy + height) % height;

}

Classe Ghost

Definizione della classe: file ghost.h

Definizione della classe: file ghost.h

Implementazione dei metodi: file ghost.cpp Implementazione dei metodi: file ghost.cpp

Le classi derivate devono implementare tutti

i metodi virtuali puri Le classi derivate devono implementare tutti

i metodi virtuali puri

(16)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Astrazione e riusabilità

Strutture dati ed algoritmi, in Field, possono essere implementati sulla classe MovingObject

Per il movimento e la posizione, si sfrutta il fatto che tutti gli oggetti MovingObject hanno i metodi necessari

move, getX, getY

Dati e algoritmi definiti in funzione della classe:

più alta nella gerarchia (più astratta), che offra le caratteristiche richieste

→ Massimizzazione di riusabilità e flessibilità

(17)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

class Field { public:

Field(int width, int height);

~Field();

void add(MovingObject* obj);

void moveAll();

void print();

private:

int width;

int height;

vector<MovingObject*> objects;

char getSymbol(int x, int y);

}

Campo da gioco generico

MovingObject Field

1

*

(18)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

const int W = 16, H =12;

Field* field = new Field(W, H);

field->add(new Ball(4, 8, +1, +1, W, H));

field->add(new Ghost(12, 4, W, H));

field->print();

string line;

while (getline(cin, line)) { field->moveAll();

field->print();

}

delete field;

Oggetti in movimento

Fill a field with

objects Fill a field with

objects

Move objects

Move objects

Delete field and

Delete field and

(19)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Quando usare l'ereditarietà? Due fasi diverse:

Nella fase di analisi per modellare il problema

Nella fase di progettazione, per modellare la soluzione e massimizzare il riuso, tramite astrazione

… Progetto delineato a partire dal modello di analisi

Classe derivata usata allo stesso modo e al posto della sua classe base?

Eckel: ereditarietà o composizione?

“Do I need to upcast?”

Progettare tramite astrazioni

(20)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Massimizzare il riuso

Ereditare codice e dati di una classe esistente

Ma si eredita anche l'interfaccia!

Es. Circle estende Point e aggiunge radius?

No, per questo scopo è meglio usare la composizione Relazione: is-a oppure has-a?

Riusare e specializzare un intero sistema esistente, mediante la realizzazione di certe classi astratte

Si progetta il sistema ad alto livello di astrazione

Poi si aggiungono nuove classi specializzate

(21)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Ereditarietà C++ vs. Java

Ereditarietà multipla tra le classi C++

Una classe può avere più classi base dirette

Java: ereditarietà singola + interfacce

Non esiste una classe radice, da cui tutte le classi implicitamente derivano

Java: Object , base di tutte le classi

(22)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Classe astratta pura: solo metodi pure virtual

Insieme delle signature dei metodi pubblici

Senza corpo dei metodi, senza implementazione Classe MovingObject: in effetti una interfaccia

Modello più “pulito”, attenzione ai servizi

Cosa un oggetto sa fare, non come lo fa Possibilità di migliorare la riusabilità

La classe di implementazione sceglie come memorizzare lo stato ed implementare i metodi

No “diamond problem”...

Interfacce

(23)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Ereditarietà multipla

Un veicolo anfibio è contemporaneamente…

Un veicolo terrestre Un veicolo acquatico

Una classe AmphibiousCar dovrebbe estendere sia Car che Motorboat

Se ereditarietà multipla...

Quale stato usare?

Quali metodi eseguire?

“Diamond problem”

(24)

olo – Fondamenti di informaticaolo – Fondamenti di informatica neria dell'informazione – UniPRneria dell'informazione – UniPR .ce.unipr.it/people/tomamic/.ce.unipr.it/people/tomamic/

Interfacce per veicoli

Vehicle

Car Motorboat Bicycle

ConcreteBicycle ConcreteMotorboat

AmphibiousCar

ConcreteCar

(25)

Tomaiuolo – Fondamenti di informaticaTomaiuolo – Fondamenti di informatica . Ingegneria dell'informazione – UniPR. Ingegneria dell'informazione – UniPR p://www.ce.unipr.it/people/tomamic/p://www.ce.unipr.it/people/tomamic/

Librerie e framework

Ma introdurre un’interfaccia per ogni classe non è sempre l’approccio migliore!

Libreria: l'utente usa...

Poche e semplici astrazioni chiave

Possibile separazione tra interfacce e implementazione, dietro le quinte (factory)

Framework: l'utente fornisce...

Implementazione di metodi di certe classi astratte

Classi che implementano certe interfacce

Riferimenti

Documenti correlati

aiuolo – Fondamenti di informaticaaiuolo – Fondamenti di informatica egneria dell'informazione – UniPR egneria dell'informazione –

Fondamenti di informatica Fondamenti di informatica dell'informazione – UniPR dell'informazione – UniPR unipr.it/people/tomamic/unipr.it/people/tomamic/.. Caratteristiche

Successivamente è stato analizzato il processo produttivo all’interno del caseificio per ottenere la caciotta e la ricotta; le informazioni relative alle fasi di produzione e

In generale, per qualunque impiego di MOGM in Ateneo, gli operatori devono essere forniti di dispositivi di protezione individuale (DPI), l’accesso deve essere controllato, deve

Così ad esempio, alla metà degli anni '90 del secolo scorso, due antropologi di rilievo come Marc Augè e Clifford Geertz, con un background culturale differente,

This paper reviews the major (Calcium, Phosphorus, Potassium, Sodium, Chlorine, Sulphur, Magnesium) and the trace elements (Iron, Copper, Cobalt, Iodine, Manganese, Zync,

● Fare riferimento alla pagina del corso per sapere di volta in volta quale è il proprio turno.. Per evitare i disagi che si sono verificati negli anni precedenti non saranno

• Una variabile è un ente, appartenente ad un certo tipo, che può assumere uno qualunque dei valori appartenenti al tipo. • Una variabile è identificata da un