Informatica 3. LEZIONE 8: Fondamenti di programmazione orientata agli oggetti (2)

Documenti analoghi
Informatica 3. Informatica 3. LEZIONE 8: Fondamenti di programmazione orientata agli oggetti (2) Lezione 8 - Modulo 1

Corso di Algoritmi e Strutture dati Programmazione Object- Oriented in Java (Parte I)

Programmazione Java Avanzata Programmazione Object- Oriented in Java

Classi. Oggetti e classi. Creazione e inizializzazione di oggetti in C++ Distruzione di oggetti in C++

Ereditarietà e polimorfismo

A. Lorenzi, A. Rizzi Java. Programmazione ad oggetti e applicazioni Android Istituto Italiano Edizioni Atlas

Riassunto: cos è la OOP? classi astratte, interfacce, classi interne. Scaletta. Figura con area()? Figura senza area()? Stefano Mizzaro 1.

Esempio 2: Subtyping

Object-Oriented Technology. Giuliano Armano 1

L ereditarieta` Riuso del software: Ereditarieta`, Composizione, Polimorfismo e Binding Dinamico Ereditarietà Ereditarietà

La classe java.lang.object

Programmazione ad oggetti

Risoluzione dei metodi

Programmazione Orientata agli Oggetti

Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

Programmazione a Oggetti Lezione 7. Il linguaggio Java: aspetti generali

Ereditarietà e Polimorfismo. Prof. Francesco Accarino IIS Altiero Spinelli Via Leopardi 132 Sesto San Giovanni

Catia Trubiani. Laboratorio di Ingegneria del Software a.a

Ingegneria del Software

18 - Classi parzialmente definite: Classi Astratte e Interfacce

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 2

Lettura e scrittura di file di dati input/output

Gerarchia di classi Java 1

Riassunto. La programmazione OO. Oggi. Esempio

Programmazione ad Oggetti

Programmazione a oggetti

Informatica 3. LEZIONE 2: Sintassi e semantica

Lezione 13 Classi interne

Programmazione orientata agli oggetti Ereditarietà

Informatica 3. Informatica 3. LEZIONE 2: Sintassi e semantica. Lezione 2- Modulo 1. Le componenti di un linguaggio di programmazione

16 - Ereditarietà, tipi e gerarchie

16 - Ereditarietà, tipi e gerarchie

RETI DI CALCOLATORI Linguaggio Java: Ereditarietà

Laboratorio di programmazione

INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

Ereditarietà e Polimorfismo

Linguaggio C - sezione dichiarativa: costanti e variabili

Funzioni, Stack e Visibilità delle Variabili in C

Introduzione alla programmazione Object Oriented. Luca Lista

Programmazione orientata agli oggetti La classe Object, metodi e classi final, this. Object

Programmazione orientata agli oggetti La classe Object, metodi e classi final, this. Object

Object-Oriented Programming

Informatica 3. Informatica 3. LEZIONE 5: Tipi di dati. Lezione 5 - Modulo 1. Tipi predefiniti. Introduzione

Programmazione con Java

Fondamenti di Informatica T-1. Ereditarietà & Polimorfismo

Principi di Progettazione del Software a.a

Indice generale Introduzione...vii Parte I Concetti e costrutti fondamentali... 1 Capitolo 1 Introduzione al linguaggio... 3

Capitolo 6. Uso della gerarchia. c 2005 Pearson Education Italia Capitolo 6-1 / 125

Informatica 3. LEZIONE 5: Tipi di dati

Definizione di classi. Walter Didimo

Esempio Principio di sostituibilità

e il loro uso: esistente e cambiare quel che va cambiato specializzare (per ereditarietà) la classe Counter public class EsempioNuovo {

Classi astratte. Nella gerarchia delle classi, potrebbe essere utile prevedere un supertipo generale per le classi che si usano. Ad esempio: Figura

Proprietà delle Classi e degli Oggetti in Java

Tipi di Dati Astratti

Le basi del linguaggio Java

Informatica 3. Informatica 3. Lezione 1- Modulo 1. LEZIONE 1: Introduzione. Concetti di linguaggi di programmazione. Introduzione

Informatica 3. LEZIONE 1: Introduzione. Modulo 1: Introduzione al corso Modulo 2: Introduzione ai linguaggi di programmazione

I Template in C++ Corso di Linguaggi di Programmazione ad Oggetti 1. a cura di: Giancarlo Cherchi

Proprietà delle Classi e degli Oggetti in Java

Obiettivi. Comprendere i vantaggi offerti dal meccanismo dell ereditarietà Attivare processi di astrazione e specializzazione.

Richiami su oggetti e OOP

Basi di dati a oggetti

La programmazione ad oggetti: chiamate di metodi. Overloading. This

La programmazione ad oggetti (OOP)

RICHIAMI DI PROGRAMMAZIONE A OGGETTI. Corso di Informatica Medica

19 - Eccezioni. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

14 - Metodi e Costruttori

Concetto di Funzione e Procedura METODI in Java

Programmazione Orientata agli Oggetti. Emilio Di Giacomo e Walter Didimo

Ereditarietà. Ereditarietà. Ereditarietà. Ereditarietà

Fondamenti di Informatica 1. Prof. B.Buttarazzi A.A. 2010/2011

Esempi al calcolatore su: 1) Costruttori ed ereditarietà 2) Subtyping e polimorfismo

Programmazione orientata agli oggetti Subtyping e polimorfismo

Funzioni costruttore e istanza di un'oggetto

Informatica I. Ingegneria Medica. Prof. Diego Salamon

Ereditarietà (ultima)

Programmazione ad oggetti

Corso di Programmazione ad Oggetti

Classi, Ereditarietà e Polimorfismo. Lezione 7

Lezione 1 - Relazioni tra classi

Corso di Laurea in Bioinformatica Dipartimento di Informatica - Università di Verona

Informatica 1 Tipi e dichiarazioni in C++ C++ - Tipi e dichiarazioni 1

Sul pattern Iterator

Sommario. Introduzione... xv. Giorno 1 Elementi base del linguaggio C

Programmazione orientata agli oggetti Classi astratte e interfacce

Programmazione orientata agli oggetti

Eredità e Polimorfismo in Java

Corso sul linguaggio Java

Corso di Programmazione a oggetti

Programmazione Java: Polimorfismo

Puntatori. Obiettivi: Richiamare quanto noto sui puntatori dal modulo A Presentare l analogia tra puntatori e vettori e l aritmetica dei puntatori

Uso di classi e oggetti. Prof. Francesco Acarino IIS Altiero Spinelli Via Leopardi 132 Sesto San Giovanni

Derivazione di Classi

IL CONCETTO DI CLASSE

Costanti e Variabili

Esempi in Java di program.ne O-O

Programmazione Java Struttura di una classe, Costruttore, Riferimento this

Elementi lessicali. Lezione 4. La parole chiave. Elementi lessicali. Elementi lessicali e espressioni logiche. Linguaggi di Programmazione I

Transcript:

Informatica 3 LEZIONE 8: Fondamenti di programmazione orientata agli oggetti (2) Modulo 1: Ereditarietà Modulo 2: Polimorfismo e classi astratte Modulo 3: Visibilità delle proprietà di una classe Modulo 4: Assegnamento e uguaglianza Modulo 5: Genericità in C++

Informatica 3 Lezione 8 - Modulo 1 Ereditarietà

Generalizzazione e ereditarietà Principali astrazioni impiegate per condividere similitudini tra classi pur preservandone le indipendenze Generalizzazione o relazione IS-A: relazione tra una classe (super-classe o classe base) e una o più versioni specializzate della classe (sotto-classi o classi derivate) Persona Docente Studente Tutor Studente IOL Ogni sotto-classe eredita le caratteristiche della super-classe Ogni istanza di una sotto-classe è (IS-A) un istanza della superclasse

Generalizzazione e ereditarietà (2) Vale la proprietà di transitività Concetto di antenato e discendente di una classe Ogni istanza di una sotto-classe è un istanza di tutte le classi antenato Lo stato di un istanza include il valore per ogni attributo di ogni classe antenato Una qualsiasi operazione di una qualsiasi classe antenato può essere applicata ad un istanza Lo stesso principio si può applicare agli oggetti di un programma. La generalizzazione viene implementata definendo un nuovo tipo come estensione di un tipo preesistente. I linguaggi OO supportano la nozione di ereditarietà

Implementazione dell ereditarietà class Persona { //attributi stringa nome; stringa cognome; public: //servizi... } classe base class Studente: public Persona { //attributi int matricola; public: //servizi... } classe derivata La classe Studente specializza la classe Persona aggiungendo ulteriori informazioni come ad es. il numero di matricola

Creazione e distruzione di oggetti derivati Il costruttore di una classe derivata viene invocato dopo il costruttore della classe base in questo modo si garantisce che le variabili ereditate siano disponibili all oggetto derivato La distruzione di una classe derivata procede in direzione opposta: si invoca prima il distruttore della classe derivata e successivamente il distruttore della classe base

Generalizzazione vs. aggregazione La generalizzazione si riferisce alle classi ed è un modo per strutturare la descrizione di un singolo oggetto la super-classe e la sotto-classe si riferiscono alle proprietà di uno stesso oggetto L aggregazione si riferisce alle istanze vengono coinvolti due oggetti in cui uno è parte dell altro Entrambe si possono rappresentare tramite un albero nell aggregazione l albero è costituito da istanze di oggetti che sono tutti parte di un oggetto composito relazione AND: un libro è costituito da una copertina e da un insieme di pagine nella generalizzazione l albero è composto da classi che descrivono un oggetto relazione OR: un libro può essere un libro di storia oppure di informatica Copertina Libro di storia Libro Libro Pagine Libro di informatica

Ereditarietà multipla L ereditarietà multipla consente ad una classe di avere più di una super-classe e di ereditare le caratteristiche di tutti i suoi antenati Consente di miscelare informazioni da due o più sorgenti In C++ si ottiene ponendo il simbolo : dopo la definizione di classe seguita dalla lista delle classi da cui deriva separate da, I costruttori sono chiamati nell ordine di ereditarietà specificato

Esempio di ereditarietà multipla class Studente: public Persona { //attributi int matricola; public: //servizi }; class Lavoratore: public Persona { //attributi char* qualifica; public: //servizi }; class StudenteLavoratore : public Studente, public Lavoratore {... };

Overloading e overriding di operazioni Quando due funzioni caratterizzate da parametri di input diversi utilizzano lo stesso nome si parla di overloading Es. int square (int); double square (double); lo stesso nome viene sovraccaricato con significati differenti Una sotto-classe può effettuare un overriding (sovrascrittura) delle proprietà della super-classe definendo una proprietà con lo stesso nome e signature identiche [in C++] la proprietà della sotto-classe raffina e sostituisce la proprietà della super-classe

Esempio di overriding class Persona { //attributi stringa nome; stringa cognome; public: //servizi void presentati(); } Buongiorno, sono <nome> <cognome> class Studente: public Persona { //attributi int matricola; public: //servizi void presentati(); } Buongiorno, sono <nome> <cognome>, matricola numero <matricola>

Overriding in altri linguaggi Altri linguaggi di programmazione rilassano il vincolo di avere la stessa signature in caso di overriding, basandosi sulle seguenti regole di controllo di tipi: Regola di controvarianza I parametri di input della funzione che sovrascrive devono essere un supertipo dei parametri corrispondenti della funzione sovrascritta Regola di covarianza Il valore restituito dalla funzione che sovrascrive deve essere un sottotipo del valore restituito dalla funzione sovrascritta C++ e Java non seguono nessuna di queste regole: la funzione che sovrascrive e la funzione sovrascritta devono essere uguali Ada e Eiffel richiedono la covarianza sia sui parametri di input che sul valore restituito Emerald rispetta queste due regole

Ereditarietà e compatibilità Compatibilità di tipo: la classe discendente costituisce un tipo che può essere sempre usato al posto del tipo della classe antenato (uno Studente S è sempre una Persona) il viceversa non vale! (una Persona non può sempre essere utilizzata dove ci si aspetta uno Studente) il tipo derivato (Studente) si dice sottotipo (subtype) del tipo base (Persona)

Ereditarietà e compatibilità in C++ class Persona { //attributi stringa nome; stringa cognome; public: //servizi void presentati(); } class Studente: public Persona { //attributi int matricola; public: //servizi void presentati(); } Persona * pp = new Persona; Studente * ps = new Studente;... pp = ps; // OK: in C++ i puntatori sono // polimorfici (upcasting) ps = pp; // KO: C++ ha un sistema di tipi forte Persona p; Studente s;... p = s; // OK: coercizione s = p; // KO

Informatica 3 Lezione 8 - Modulo 2 Polimorfismo e classi astratte

Problema Persona * pp = new Persona( Mario, Rossi ); Studente * ps = new Studente( Paolo, Bianchi, 555431);... pp = ps; // upcasting pp->presentati();??? Buongiorno, sono Paolo Bianchi Il binding tra il tipo dell oggetto a cui si riferisce pp e la sua implementazione è stabilito a tempo di compilazione Per risolvere questo problema occorre sfruttare il concetto di late binding in C++ viene implementato tramite le funzioni virtuali

Funzioni virtuali Funzione virtuale: si dichiara facendo precedere il suo prototipo dalla parola chiave virtual nella classe base una funzione dichiarata virtuale resta virtuale in tutta la gerarchia dell ereditarietà è buona norma dichiarare esplicitamente le funzioni virtuali ad ogni livello class Persona { //attributi stringa nome; stringa cognome; public: //servizi virtual void presentati(); } class Studente: public Persona { //attributi int matricola; public: //servizi virtual void presentati(); }

Late binding Late binding: chiedere ad un oggetto lo svolgimento di un servizio, lasciando che il sistema scelga a tempo di esecuzione la versione del servizio più opportuna, in base al ruolo corrente dell'oggetto Persona * pp = new Persona( Mario, Rossi ); Studente * ps = new Studente( Paolo, Bianchi, 555431);... pp->presentati(); ps->presentati(); pp = ps; pp->presentati(); Buongiorno, sono Paolo Bianchi, matricola numero 555431 Buongiorno, sono Mario Rossi Buongiorno, sono Paolo Bianchi, matricola numero 555431

Polimorfismo Con il late binding il puntatore pp diventa polimorfico Polimorfismo: concetto generale di programmazione OO secondo il quale la stessa operazione può comportarsi in modo differente per oggetti di classi diverse appartenenti alla stessa gerarchia di ereditarietà In C++ il polimorfismo delle variabili viene limitato: una variabile di una classe T può riferirsi solamente ad oggetti di tipo T oppure ad oggetti appartenenti a classi derivate da T solamente puntatori, riferimenti a variabili e parametri passati per riferimento possono essere polimorfici

Controllo dei tipi Osservazione sul controllo dei tipi: la funzione virtuale viene definita nella classe base: è quindi disponibile in tutte le classi derivate, anche se queste non la ridefiniscono qualsiasi ridefinizione della funzione virtuale deve mantenere la stessa signature Anche se il compilatore non conosce a priori con quale funzione verrà effettuato il binding a tempo di esecuzione, può garantire che questa funzione esiste ed avrà la signature corretta Il C++ è fortemente tipizzato

Classi astratte Una classe astratta è una classe che non può essere istanziata Da una classe astratta è possibile derivare classi concrete, cioè istanziabili tutte le foglie dell albero che rappresenta la relazione di ereditarietà devono essere classi concrete Le classi astratte organizzano caratteristiche comuni a diverse classi si utilizzano per rappresentare gli ADT (metodi a livello astratto) si derivano poi le classi concrete che implementano i metodi della classe astratta

Classi astratte in C++ In C++ una classe astratta contiene funzioni virtuali pure (che non hanno un implementazione) che saranno definite nelle classi derivate class Poligono { //classe astratta //attributi Punto * vertici; //lista di vertici... public: //servizi virtual void disegna() = 0; // funzione virtuale pura virtual void ruota() = 0; // funzione virtuale pura }; Una classe è astratta se possiede almeno una funzione virtuale pura, locale o ereditata Una classe astratta può essere usata solo per dichiarare variabili polimorfiche

Classi astratte in C++ class Triangolo: public Poligono { //attributi... public: //servizi virtual void disegna(); //overriding virtual void ruota(); //overriding... }; class Rettangolo: public Poligono { //attributi... public: //servizi virtual void disegna(); //overriding virtual void ruota(); //overriding... }; void disegnapoligono(poligono & p) { p.disegna(); } void main () { Triangolo t; Variabile polimorfica Rettangolo r; p punta a t quando si invoca disegnapoligono (t) Viene chiamata disegna() definita in Triangolo disegnapoligono (t); p punta a r quando si invoca disegnapoligono (r) disegnapoligono (r); Viene chiamata disegna() definita in Rettangolo }

Informatica 3 Lezione 8 - Modulo 3 Visibilità delle proprietà di una classe

Controllo dell accesso alle caratteristiche ereditate La relazione di ereditarietà consente alla classe derivata di riusare caratteristiche della classe base servizi attributi La classe derivata diventa un cliente speciale della classe base: può vederne (se consentito) anche dettagli interni invisibili ai clienti esterni Che cosa può usare la classe derivata della classe base? Che cosa può vedere chi utilizza la classe derivata di ciò che questa eredita dalla classe base?

Livelli di visibilità delle caratteristiche Il livello di visibilità delle caratteristiche di una classe indica chi può vedere tali caratteristiche Un servizio/attributo può essere: private: visibile soltanto ai servizi (o a funzioni friend) della stessa classe in cui è dichiarato protected: visibile soltanto ai servizi (o a funzioni friend) della stessa classe in cui è dichiarato e delle classi da essa derivate public: visibile a tutti (anche a clienti esterni) Se una funzione viene dichiarata come friend ha gli stessi diritti della classe stessa

Visibilità erede-antenato Es. class Studente: public Persona { }; La visibilità erede-antenato dice a chi l'erede rende visibili le caratteristiche ereditate dall antenato Il rapporto tra erede e antenato può essere: public: le caratteristiche ereditate mantengono lo stato di visibilità che hanno nella classe base ad es., le caratteristiche private non sono visibili all'erede diretto, quelle protette non sono visibili ai clienti dell'erede diretto, ma solo ai discendenti protected: le caratteristiche ereditate pubbliche e protette sono rese visibili ai soli discendenti (non ai clienti). private: le caratteristiche ereditate pubbliche e protette sono visibili al solo erede diretto (nè ai discendenti, nè ai clienti).

Esempio class d1 : private base { }; class base { private: int a; public: int b,c; }; class d2: protected base { }; class d3 : public d1 { void set-abc(){ a=1; // ko: base::a privato b=2; // ko: d1::base privato c=3; // ko: d1::base privato! }; void main() }; { d1 X1; d2 X2; X1.b=2; // ko: privato X1.c=3; // ko: privato X2.b=2; // ko: protetto X2.c=3; // ko: protetto } class d4 : public d2 { void set-abc(){ a=1; // ko: base::a privato b=2; // ok: d2::b // accessibile (protetto) c=3; // ok: d2::c //accessibile (protetto) }; };

Informatica 3 Lezione 8 - Modulo 4 Assegnamento e uguaglianza

Assegnamento e uguaglianza tra classi Il C++ per le classi definisce di default oltre a costruttore e distruttore anche gli operatori = e == Esempio: class Persona { //attributi stringa nome; stringa cognome; Auto * a; public: //servizi }; class Auto { //attributi stringa modello; stringa targa; public: //servizi }; p1 Mario Rossi a1 Ferrari IOL003

Assegnamento e uguaglianza tra oggetti La presenza di riferimenti a oggetti esterni consente di interpretare uguaglianza e assegnamento tra oggetti in due modi: Interpretazione superficiale Assegnamento e uguaglianza vengono applicate campo per campo ersona p1, p2; 2=p1; //superf. p1 Mario Rossi a1 Ferrari IOL003 Mario Rossi p2

Assegnamento e uguaglianza tra oggetti La presenza di riferimenti a oggetti esterni consente di interpretare uguaglianza e assegnamento tra oggetti in due modi: Interpretazione superficiale Assegnamento e uguaglianza vengono applicate campo per campo Interpretazione profonda Assegnamento e uguaglianza vengono applicate considerando ricorsivamente gli oggetti collegati ersona p1, p3; 3=p1; //prof. p1 Mario Rossi a1 Ferrari IOL003 p3 Mario Rossi a3 Ferrari IOL003 I linguaggi di programmazione forniscono di default l'interpretazione superficiale

Informatica 3 Lezione 8 - Modulo 5 Genericità in C++

Genericità Problema: esistono strutture dati che rappresentano contenitori di altri dati (ad es. array, liste, pile, alberi, ecc.) Es. array può contenere int, float, Persona, Studente,.. per evitare di implementare la stessa struttura dati per ogni tipo di dato occorre sviluppare dei meccanismi per rendere il codice generico e riusabile Soluzione classica nella programmazione OO: utilizzare ereditarietà + polimorfismo [Java, Smalltalk] tutti gli oggetti derivano da un oggetto base che rappresenta l antenato di tutti i possibili oggetti che possono essere utilizzati all interno di un programma Es. classe Object di Java o Smalltalk le strutture dati contenitore puntano a questi tipi di oggetti e attraverso il polimorfismo possono essere applicate ad oggetti di tipo diverso Problema: tutte le classi fanno parte di un unico albero di ereditarietà

Genericità in C++ Il linguaggio C++ non forza ad utilizzare una gerarchia basata su un singolo oggetto, ma permette di risolvere il problema tramite i TEMPLATE I template rappresentano un modo alternativo all ereditarietà per riusare codice ereditarietà: riuso di codice oggetto template: riuso di codice sorgente In C++ i template implementano il concetto di tipo parametrizzato Quando si usa un template vengono specificati dei parametri generici, che verranno sostituiti dal compilatore con i tipi specificati nel programma

Sintassi dei template La parola chiave template specifica che la definizione di classe che segue utilizzerà uno o più tipi non specificati I tipi dovranno essere specificati quando il codice deve essere effettivamente generato template<class T> class Array { T A[N]; public: //servizi array }; int main() { Array<int> ia; Array<float> fa; for (int i=0; i<n; i++){ ia[i]=i; fa[i]=(float)i; } Il compilatore, all istanziazione del template in cui viene specificato il tipo del parametro, espande il template generando la classe con il tipo specificato (riuso di codice sorgente)