Tecnologia OO.

Slides:



Advertisements
Presentazioni simili
Oggetti Java.
Advertisements

Differenze nei vari linguaggi di Elisa Trifirò e Barbara Tacchino
Alcune Classi Standard Object, Vettori. Esercizio dellultima volta Superclasse Persona Sottoclasse Libro.
Le gerarchie di tipi.
LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.
Java base IV: Java e la programmazione O.O.
IL TEMA DELLA RIUSABILITÀ Si vuole riusare tutto ciò che può essere riusato (componenti, codice, astrazioni) Non è utile né opportuno modificare codice.
IL TEMA DELLA RIUSABILITÀ Si vuole riusare tutto ciò che può essere riusato (componenti, codice, astrazioni) Non è utile né opportuno modificare codice.
I nomi in Java F. Bombi 18 novembre novembre 2003.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Fondamenti di informatica Oggetti e Java Luca Cabibbo Luca Cabibbo – Fondamenti di informatica: Oggetti e Java Copyright © 2004 – The McGraw-Hill Companies.
Programmazione in Java. Classi I programmi in Java consistono di classi. Le classi consentono di definire: collezioni di procedure (metodi statici) tipi.
Esercitazione del 7 marzo 2008 Ereditarieta’. Esercizio: soluzione Implementare la seguente specifica che definisce un tipo di dato Libro.
Cose nuove di Java (prima a chiacchiera, poi formalmente)
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Esercitazione del 9 marzo 2007 Ereditarieta’. Richiami Definire sottoclassi (ereditarieta’) Overriding Specificatori di accesso (private, protected) Principio.
Corso di Algoritmi e Strutture Dati con Laboratorio Richiami di Java – parte II.
Introduzione all’Ereditarietà Pietro Palladino. Richiami UML Classe: descrizione di un insieme di oggetti software con caratteristiche simili Definisce.
Table View. Problemi ricorrenti Una situazione ricorrente è quella in cui il controller potrebbe avere un’altezza superiore a quella dello schermo. In.
Fondamenti di Informatica - D. Talia - UNICAL 1 Fondamenti di Informatica FONDAMENTI DI INFORMATICA Domenico Talia
1 Elementi DI INFORMATICA Università degli Studi di Cagliari Corso di Laurea in Ingegneria Elettronica Linguaggio C A.A. 2011/2012
Programmazione in Java Parte I: Fondamenti Lezione 1 Dott. Marco Faella.
Programmazione orientata agli Oggetti. Classi Le classi sono uno strumento per costruire strutture dati che contengano non solo dati ma anche il codice.
.  I tipi di dati non primitivi sono gli array, le struct e le union.  Gli array sono degli aggregati di variabili dello stesso tipo.  La dichiarazione.
Ereditarietà Uno dei principi della programmazione orientata agli oggetti (OOP) è il riuso Le classi dovrebbero essere progettate come componenti riutilizzabili.
Maurizio Cozzetto, Francesco Sarasini
Universita’ di Milano Bicocca Corso di Basi di dati 1 in eLearning C
Approcci nella soluzione di un problema
Programmazione a oggetti
Unità didattica 1: Introduzione al linguaggio Java
I vincoli di integrità Alcuni aspetti della realtà NON possono essere modellati solamente con entità, attributi e relazioni, per esempio i vincoli di integrità.
Programmazione a oggetti
Tipo di dato: array Un array è un tipo di dato usato per memorizzare una collezione di variabili dello stesso tipo. Per memorizzare una collezione di 7.
Informatica per l’Ingegneria
Programmazione ad Oggetti per la Fisica
Corso Java Introduzione.
Gli oggetti: concetti avanzati
Corso Java Esercitazione.
Corso di Laurea Ingegneria Informatica Fondamenti di Informatica
FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a. a
OBJECT ORIENTED DATABASE
Corso Java Cicli e Array.
Package Pacchetti e ereditarietà 29/12/2018 package.
Esercitazioni di C++ 31 dicembre 2018 Claudio Rocchini IGMI.
Oggetti Java.
Corso Java Matrici.
Copia di oggetti il costruttore di copia ha le stesse particolarità della signature di un costruttore ordinario; il primo parametro è una reference ad.
Composizioni di classi
Sommario cos’è un tipo di dato astratto astrazione tramite specifica:
Il passaggio dei parametri Metodi statici Il riferimento this
Ricorsione 16/01/2019 package.
APPUNTI SUL LINGUAGGIO C
Corso di Laurea Ingegneria Informatica Fondamenti di Informatica
Corso di Laurea Ingegneria Informatica Fondamenti di Informatica
Condizioni decisionali
Corso di Algoritmi e Strutture Dati APPUNTI SUL LINGUAGGIO C
APPUNTI SUL LINGUAGGIO C
Java Costruttore di copia e GetStatus.
Condizioni decisionali
Corso Java Lezione 1 5/12/2019.
UML Diagramma statico di una classe
Array e Stringhe Linguaggio C.
Docente: Sabato Bufano
Ese 1 (del 31 Marzo 2004).
Ese 3 (del 3 Aprile 2003).
Transcript della presentazione:

Tecnologia OO

Information Hiding Attributi nascosti accessibili mediante opportuni metodi

ereditarietà

Costruzione modulare e incrementale Il software dovrebbe essere protetto, riusabile, documentato, modulare, incrementalmente estendibile   L’OBIETTIVO • costruzione modulare e incrementale del software ottenuta per estensione / specializzazione di componenti tecnologia component-based LE NECESSITÀ • servono strumenti per la costruzione modulare e incrementale del software

UN MECCANISMO RISOLUTIVO: EREDITARIETÀ •l’ereditarietà serve per non ripartire da zero quando serve una nuova classe, permettendo di poterla definire a partire da una già esistente nella logica del riuso

Java: gerarchia di classi ereditarietà singola Tutte le classi Java ereditano da Object Ereditarietà singola: ogni classe, unica superclasse

Ereditarietà: sottoclassi Bisognerà specificare ciò che distingue la classe figlia dalla madre: •cosa la nuova classe ha in più rispetto alla precedente sia in termini di dati, sia in termini di operazioni •cosa la nuova classe ha di diverso rispetto alla precedente sia in termini di operazioni.   ogni classe derivata eredita tutte le proprietà della classe base di partenza.

Esempio: classe Persona e sottoclassi

Ereditarietà: sottoclassi LA CLASSE DERIVATA PUÒ: • aggiungere nuovi campi dati e nuovi metodi a quelli ereditati dalla madre • ridefinire alcuni dei metodi ereditati dalla madre POLIMORFISMO   LA CLASSE DERIVATA NON PUÒ: •eliminare campi dati o metodi (comportamento monotono, si accresce sempre) Ridefinire (sovrascrivere) Sovraccaricare

Ereditarietà : costruttori Per costruire un oggetto di una classe derivata, è sempre opportuno chiamare un costruttore della classe madre, in quanto:   •solo il costruttore della classe madre può sapere come inizializzare i campi-dati ereditati da tale classe in modo corretto •è il solo modo per garantire l’inizializzazione di campi-dati privati (a cui la sottoclasse non può accedere direttamente) •si evita una inutile duplicazione di codice nella sottoclasse. riuso

Ereditarietà : costruttori Quale costruttore della classe madre viene chiamato?   • il costruttore di default definito da Java (se noi non lo definiamo) chiama il costruttore di default della classe madre (se questo non esiste si ha errore). Tale costruttore della classe figlia è pubblico ed invoca il costruttore della superclasse • per i costruttori definiti dall’utente occorre specificare esplicitamente quale costruttore della classe madre vada chiamato, mediante la notazione super(..), che deve essere la prima istruzione nel corpo del costruttore. Se manca, Java di solito inserisce automaticamente una chiamata al costruttore di default della classe madre cioè super() non parametrico

Ereditarietà: sintassi in Java public class <Nuova_(sotto)classe> extends <Vecchia_(super)classe> { <nuove_variabili_istanza> <nuovi_metodi> } public class Donna extends Persona{ public class Uomo extends Persona{

Ereditarietà: omonimie NB: • this è un riferimento all’istanza corrente super è un riferimento alla classe madre   Sono espressioni lecite: • this.val che indica il campo val della classe dell’istanza corrente • this.f() che richiama il metodo f() della classe dell’istanza corrente • super(..) che richiama un costruttore parametrico della classe madre • super.val che indica il campo val della classe madre • super.f() che richiama il metodo f() della classe madre Le ultime due notazioni sono utili se la sottoclasse definisce un campo dati o un metodo omonimo con uno della classe madre

Visibilità Nella classe madre: Perciò, la classe derivata: • ciò che è privato è visibile solo ai metodi della classe stessa • ciò che è di package è visibile solo ai metodi delle classi dello stesso package • ciò che è pubblico è visibile a tutti   Perciò, la classe derivata: • non può vedere la parte privata della madre, appunto perché privata; • può vedere la parte di package della madre, purché la nuova classe sia definita nello stesso package • vede, ovviamente, la parte pubblica della madre, in quanto visibile a tutti. Ma non basta…..

Protected Per sfruttare davvero l’ereditarietà occorre superare la rigidità dei tre livelli di visibilità privato / pubblico / package: occorre una visibilità specifica per le classi derivate   protected

Protected Un campo dati o un metodo protected:   • è visibile alle classi derivate indipendentemente dal package in cui esse sono definite • per il resto si comporta come la visibilità package.

Protected La qualifica protected: occorre dunque valutare con attenzione quando sia opportuna.   • rende visibile un attributo a tutte le sottoclassi di quella classe, presenti e future • perciò, costituisce un permesso di accesso “indiscriminato”, valido per ogni possibile sottoclasse che possa in futuro essere definita, senza possibilità di distinzione.

polimorfismo ereditarietà

POLIMORFISMO  Una funzione si dice POLIMORFA se è capace di operare su oggetti di tipo diverso specializzando il suo comportamento in base al tipo dell’oggetto su cui opera  Ad esempio il metodo fai_verso() per un cane sarà abbaiare, per un gatto miagolare.

POLIMORFISMO: forma diversa I linguaggi a oggetti hanno intrinseco il polimorfismo, in quanto possono esistere, in classi diverse, funzioni con lo stesso nome ma con effetti completamente diversi: operazioni di overriding (ridefinizione di metodi in una sottoclasse) oppure operazioni di overloading (definizione di metodi con lo stesso nome ma differente numero e/o tipo di parametri; ne sono tipico esempio i diversi costruttori di una classe)

parametri diversi stessa firma

Sovraccaricare un metodo (stesso nome, diversi parametri) Ridefinire un metodo Sovraccaricare un metodo (stesso nome, diversi parametri) http://pages.di.unipi.it/corradini/Didattica/LIP-07/Ereditarieta/ClasseObject/main.html

Override: tecnica per sovrascrivere public class Persona { public String toString (){ String p = " Classe Persona "; System.out.println(p); return p; } } public class Figlia extends Persona { String f = " Classe Figlia"; System.out.println(f); return f; Metodi con stessa firma

Override: regole È bene notare che ci sono delle regole da rispettare per l'override: 1) se si decide di riscrivere un metodo in una sottoclasse, dobbiamo utilizzare la stessa identica segnatura, altrimenti utilizzeremo un overload in luogo di un override. 2) il tipo di ritorno del metodo deve coincidere con quello del metodo che si sta riscrivendo. 3) il metodo ridefinito, non deve essere meno accessibile del metodo che ridefinisce. Per esempio se un metodo ereditato è dichiarato protetto, non si può ridefinire privato, ma semmai, pubblico.

Overriding massima espressione di Polimorfismo public class Persona { protected int anni=0; // Verrà ereditato da Uomo, è protected public void setAnni(int anni){ this.anni=anni; } } //fine class Persona public class Uomo extends Persona{ public void setAnni (int anni) { // Tutto uguale, overriding this.anni=anni*2; } public void setAnni (double anni){ // Non c'è overriding (lista parametri diversi), // ma c'è overloading //... neonato 0.5 } } // fine class Uomo

Overloading: tecnica per sovraccaricare Metodi con lo stesso nome public int somma(int a, int b){      return a + b; } public double somma(double a, double b){    return a + b; } lista di argomenti differente

Un altro esempio Codice commentato e scaricabile

Un altro esempio: Persona public class Persona{ String nome; // public  visibilità massima String indirizzo; // public public Persona(){ this("John Doe","ignoto"); } public Persona(String nome) { this(nome,"ignoto"); } public Persona(String nome, String indirizzo){ this.nome = nome; this.indirizzo = indirizzo; } public String getNome() { return nome; } public String getIndirizzo() { return indirizzo; } public void visualizza(){ System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); } public boolean omonimo(Persona p){ return this.nome.equalsIgnoreCase(p.nome); } ... }

Un altro esempio: Studente ereditati aggiunti

Studente … senza riuso public class Studente extends Persona { // Studente eredita variabili e metodi da Persona int matricola; // nuova variabile istanza  .. per default zero    String pianoDiStudio; // nuova variabile istanza            … // si vedrà in seguito l’uso di variabili static (di classe)  // Costruttore  parametrico  non opportuno  NB: i costruttori non si ereditano public Studente(String nome, String indirizzo) { this.nome = nome; this.indirizzo = indirizzo; this.pianoDiStudio = ""; }         // nuovo metodo    public String getPdS() { return pianoDiStudio;} // nuovo metodo      public void modificaPdS(String nuovoPdS) { pianoDiStudio += nuovoPdS + "\n"; }  …}

Overriding (sovrascrittura) public class Studente extends Persona { ... // metodo sovrascritto …. senza riuso public void visualizza() { System.out.println("Nome: "+ nome + "\nIndirizzo: " + indirizzo +"\nMatricola: " + matricola + "\nPiano di Studio: " + pianoDiStudio); } }

Super Con riuso public class Studente extends Persona { … // Costruttore parametrico … con riuso public Studente(String nome, String indirizzo) { super(nome, indirizzo); // invoca costruttore della superclasse this.pianoDiStudio = ""; } //... } // metodo sovrascritto … con riuso public void visualizza() { super.visualizza(); // riuso System.out.println("Matricola: " + matricola + "\nPiano di Studio: " + pianoDiStudio); } // ...

Inclusione su di un'istanza di Studente (classe figlia) possono essere invocati anche i metodi della superclasse Persona più in generale, è possibile utilizzare un'istanza di una sottoclasse (Studente) dovunque sia richiesto un oggetto della superclasse (Persona), come in un assegnamento o nel passaggio di parametri. Persona tizio = new Studente("Mario Rossi", “via Pisa");       /* corretto: adesso su tizio posso invocare i  metodi di Persona,  grazie all'ereditarietà */       tizio. visualizza() ; Studente pippo = new Studente("Pinco Pallino", “via Empoli");       ...      if ( tizio.omonimo (pippo) )            ...       /* corretto: posso passare pippo come argomento attuale,  anche se, nel metodo, il parametro era definito di tipo Persona */

Binding (legame) dinamico in Java Il meccanismo che determina quale metodo deve essere invocato in base alla classe di appartenenza dell'oggetto si chiama binding (legame). Esiste una distinzione tra: Binding statico o early binding: il metodo da invocare viene determinato a tempo di compilazione. Binding dinamico o late binding:  il metodo viene determinato durante l'esecuzione.

Binding (legame) dinamico in Java … // cond è un intero letto da tastiera  Persona tmp;      if (cond > 0)            tmp = new Persona("Aldo Bianchi", "via Roma");       else            tmp = new Studente("Mario Rossi", "via Pisa");    tmp.visualizza();  Nell'ultimo comando, il compilatore non può sapere se a tmp sarà associata un'istanza di Persona o di Studente, perché questo dipenderà dal valore fornito dall'utente. Il binding dinamico demanda la scelta del metodo da invocare all'interprete.

Applicazione di test

Come scoprire a quale classe appartiene un oggetto Il predicato instanceof permette di controllare la classe di appartenenza di un oggetto La condizione (<unOggetto> instanceof <UnaClasse>) restituisce true se e solo se <unOggetto> è una istanza della classe <UnaClasse> ...      if (tizio instanceof Studente)                  //  ... se vero  tizio è istanza di Studente

Un altro esempio: Professore Con riuso public class Professore extends Persona{ String ruolo; int stipendio; String corsiAffidati; public Professore(String nome, String indirizzo, Strin ruolo) { // costruttore super(nome, indirizzo); // riuso this.ruolo = ruolo; this.corsiAffidati = ""; } public void setStipendio(int stipendio) { this.stipendio = stipendio; } public void aumentaStipendio(int aumento) { this.stipendio += aumento; } public void aggiungiCorso(String corso) { corsiAffidati += corso + "\n"; } public void visualizza(){ super.visualizza(); // riuso System.out.println("Ruolo: " + ruolo + "\nCorsi affidati: " + corsiAffidati); } // …}

Esercizio Progettare nell'ottica della OOP e realizzare una classe Java con nome UtilityArray che "specializza" la classe Matrice da cui eredita tutti i metodi ed "estende" la classe genitrice aggiungendo nuovi metodi necessari per implementare alcune classiche operazioni su un array monodimensionale di interi: • inserire i valori degli elementi leggendoli da tastiera (metodo ereditato) • visualizzare i valori degli elementi su video • trovare il valore massimo tra gli elementi • trovare il valore minimo tra gli elementi • effettuare la somma dei suoi elementi e calcolare il valor medio

Esercizio Inoltre proporre un'applicazione Java con nome TestUtilityArray che crea un array di 10 interi e testa le funzionalità della classe UtilityArray Specifiche La superclasse Matrice deve possedere: • attributo visibile alle classi figlie (protected): l’array di interi • un costruttore di default (che crea l'array di interi con dimensione fissa pari a 10) • altro costruttore che permette di creare l'array di interi con dimensione passata come parametro • un metodo pubblico leggiInt() per leggere da tastiera un valore intero • un metodo pubblico inizio() che inizializza l'array con valori letti da tastiera • un metodo pubblico stampa() per visualizzare su video gli elementi dell'array

Esercizio La classe UtilityArray deve possedere: • un costruttore di default (che crea l'array di interi con richiamo alla superclasse e inizializza l'attributo privato cioè la dimensione o numero di elementi dell'array) • altro costruttore con richiamo alla superclasse per creare l'array di interi con dimensione passata come parametro • metodi di accesso (in particolare, setDim() che modifica la dimensione, crea un nuovo array con la lunghezza desiderata) • un metodo inizio() che ridefinisce quello della superclasse ed inizializza l'array con valori decrescenti • metodi per trovare il valore massimo e minimo tra gli elementi • metodo per sommare i valori degli elementi e calcolare il valor medio