java 01
TRANSCRIPT
Diapositiva 1
Java
Programmazione ad oggetti
Davide [email protected]
Di cosa parleremo
Differenze tra programmazione strutturata e programmazione ad oggetti
Concetti fondamentali della OOP (Object Oriented Programming)
Classi ed istanze
La OOP ed i costrutti Java
Caratteristiche della Programmazione strutturata /1
La Programmazione strutturata si basa su alcuni basilari principi
Esistono le variabili locali e globali (strutture dati)
Esiste il concetto di blocco di istruzioni (funzione e/o procedura) che esegue un compito preciso utilizzando le variabili locali e/o globali
le variabili contengono i dati su cui il programma agisce
Le funzioni rappresentano la logica (algoritmo) da applicare sui dati per ottenere un risultato
I dati e le funzioni sono disaccoppiati nel senso che una funzione non possiede l'accesso esclusivo ad un dato
Caratteristiche della Programmazione strutturata /2
Il celebre libro di Niklaus Wirth palesa come nella programmazione strutturata la somma di Algoritmi e Strutture Dati produca i programmi
Nella OOP la separazione tra Algoritmi e Strutture Dati sparisce (o quasi).
Questa una delle pi significative differenze tra i due paradigmi di programmazione
Concetti generali della OOP
Cosa un oggetto
Incapsulamento (information hiding)
Ereditariet
Polimorfismo
Cosa un oggetto
Un oggetto una entit software dotata di
Stato
Comportamento
Pensiamo all'entit software Animale, un animale pu mangiare e muoversi, ha un nome e pu essere affamato
In genere
i verbi indicano comportamento (muoversi, mangiare)
i sostantivi (nomi) indicano lo stato (nome,et)
questa regola non e' perfetta ma abbastanza precisa
Definiamo una entit
Oggetto Animale
Stato
Nome
Fame
Colore
Comportamento
Mangiare
Muoversi
Parlare (nel senso di emettere suoni)
Fido e Polly
Stato e Comportamento
Animale
fido = new Cane(Fido);
fido.muovi();fido.parla(); // baubau
// Verifico lo statofido.getNome(); // Fidofido.getFame(); // pocafido.muovi();fido.getFame(); // molta
polly = new Pappagallo(Polly);
polly.muovi(); // si muove sul trespolo non vola!polly.parla(); // mi chiamo pooolly
// Verifico lo statopolly.getNome(); // Polly
Come sono legati stato e comportamento?
Animale
fido.muovi();
// Verifico lo statofido.getFame(); // pocapolly.muovi();
// Verifico lo statopolly.getFame();L'algoritmo presente in muovi agisce sullo stato fame cambiando i valori di alcune variabili (strutture dati) contenute negli oggetti
Non sappiamo nulla su come funziona l'algoritmo che probabilmente diverso per ogni animale
Riepilogando si pu dire che nella OOP in generale
Lo stato cambia impostando i valori di variabili (es. fame = 100)
Il comportamento lavora sulle variabili (es. incrementa il valore)
Incapsulamento /1
La fame di Fido e Polly aumenta pi velocemente se si muovono
Quando la fame al massimo supponiamo che si rifiutino di muoversi
Richiamando il metodo mangia() Fido riprender a camminare.
Posso leggere lo stato fame con getFame() e cambiarlo con mangia(), non posso dare dei valori non previsti allo stato:
questo
Incapsulamento o information hiding
Incapsulamento /2
L'information hiding
nasconde i dettagli implementativi
impedisce di falsare lo stato dell'oggetto con dei valori non
ammessi.
I valori delle variabili possono essere cambiati solo dall'oggetto
e non dall'esterno
Ereditariet /1
Sia Fido che Polly sono animali
Essi hanno in comune molte caratteristiche
Nome (stato)
Si muovono (comportamento)
Queste propriet sono dell'entit Animale e le entit Cane e Pappagallo le ereditano
Ereditariet /2
Ereditariet /3
L'ereditariet pu essere modellata secondo diversi livelli di precisione
Ereditariet /4
Ereditariet significa avere un oggetto base con un insieme di stati e comportamenti presenti anche in oggetti derivati*
Si parla di gerarchia di oggetti quando un oggetto possiede dei discendenti che a loro volta ne hanno altri (si pensi all'albero genealogico)
* ereditare e derivare sono sinonimi in OOP
Ereditariet /5
Se Fido e Polly sono uguali all'oggetto Animale che bisogno c' di creare due nuovi oggetti Cane e Pappagallo?
Si sarebbe potuto scrivere qualcosa di pi semplice
fido = new Animale("Fido") invece di fido = new Cane("Fido")
polly = new Animale("Polly") invece di polly = new Pappagallo("Polly")Gli oggetti hanno caratteristiche comuni ma non sono uguali!!Fido corre pi velocemente di PollyPolly pu volare ed anche il suono emesso diversoIl comportamento cambia e questo si chiamaPolimorfismo
Polimorfismo /1
Preso da Wikipedia, significa
assumere significati specifici in diversi contesti
Nel mondo OOP significa
la capacita' di ridefinire il comportamento di un oggetto
Sia Fido che Polly hanno un metodo parla ma il risultato un p diverso...
Il metodo parla ereditato dall'entit Animale
Polimorfismo /2
Nel caso di Fido e Polly significa che il comportamento applicato, ad esempio, nel metodo muovi cambia negli oggetti Cane e Pappagallo
Comportamento = Algoritmo; quindi il metodo Cane.muovi() e Pappagallo.muovi() contengono codice diverso
Relazioni tra classi
Le classi possono essere in relazione tra loro come
Associazione (uso di oggetti)
Aggregazione (contenimento di oggetti)
Specializzazione (ereditariet)
Relazioni / Associazione
Una classe si dice in associazione con un'altra quando esiste un legame debole o nullo
Supponiamo che esista una classe Collare, Fido potrebbe avere un attributo (field) di questo tipo.
Fido per pu tranquillamente esistere senza collare (legame debole) quindi l'attributo collare della classe pu essere vuoto
Relazioni / Aggregazione
Una classe si dice in aggregazione con un'altra quando esiste un legame forte
Supponiamo che Fido abbia l'attributo et, questo attributo deve esistere ed avere un valore valido (legame forte)
La differenza tra Associazione e Aggregazione molto sottile spesso ci si limita a dire che una classe ha un attributo di un'altra e questo attributo pu essere null oppure valorizzato
Relazioni / Specializzazione
Una classe si dice specializzazione di un'altra quando deriva da essa
Cane o Pappagallo sono specializzazioni di Animale
Animale detta classe base
La fattoria degli animali in Java
Tutti i concetti OOP trovano diretto riscontro nella sintassi del linguaggio Java
Incapsulamento (Information hiding)
Ereditariet
Polimorfismo
Prima di vedere questi aspetti prendiamo confidenza con la sintassi specifica di Java
Definire un oggetto in Java
Java utilizza la parola riservata class per definire un oggetto
class un contenitore di
variabili (che in java di chiamano field)
funzioni (che in java si chiamano metodi)
nome una variabile
getNome e setNome sono due metodi
class Animale { String nome;
String getNome() { return nome; }
void setNome(String nuovoNome){ nome = nuovoNome; }
}
Metodi con nomi "speciali"
class Animale { String nome;
String getNome() { return nome; }
void setNome(String nuovoNome){ nome = nuovoNome; }
}Java usa una convenzione per i nomi dei metodi.
Essendo una convenzione non obbligatoria ma caldamente
consigliata.
Tutti i metodi che restituiscono il valore di un field hanno il
prefisso get
Tutti i metodi che impostano il valore di un field hanno il
prefisso set
Getter e setter
I getter e setter sono normali metodi, e' solo una convenzione "umana" quella
di avere i getter che non prendono argomenti
di avere i setter che prendono un solo argomento
Nulla vieta di avere un setter che non riceve nessun argomento oppure un getter che prende uno o piu' argomenti
Un oggetto contenente getters e setters viene chiamato Java beanSi consiglia l'attenta lettura della naming conventionhttp://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html
Istanze di oggetti
Una volta definito il contenuto di una classe con field e metodi per utilizzarlo bisogna istanziarlo
Questo viene fatto con l'operatore new di Java che alloca in memoria un nuovo oggetto del tipo richiesto
Animale fido = new Animale();
Ne consegue che
Una classe rappresenta la definizione di un oggetto
Una istanza la sua struttura in memoria sulla quale possibile cambiare il valore dei field
Istanze e costruttori
Quando si crea un nuovo oggetto, ovvero una istanza, si richiama uno speciale metodo chiamato costruttore
Il costruttore ha lo stesso nome della classe e non ritorna niente
Possono esserci pi costruttori per una classe a patto che prendano parametri diversi
Se non viene dichiarato nessun costruttore Java ne crea uno automaticamente che azzera tutti i field e non riceve argomenti
Si chiama costruttore di default
Esempi di costruttori
public class Animale {}public class Animale { public Animale() { }}
Le classi sono identiche, quella a destra viene generata in fase di compilazione da Java.Attenzione! Non viene modificato il sorgente ma la classe compilata che in assenza di un costruttore viene creata con quello di defaultpublic class Animale { public Animale() { }
public Animale(String nome) { } public Animale(String nome) { } }public class Animale { public Animale() { }
public Animale(String nome) { } public Animale(String nome, String razza) { } }
Information Hiding e violazione
Il contenuto della variabile 'nome' pu essere cambiato facilmente senza nessun controllo
public class ProvaAnimaleSenzaInformationHiding { public static void main(String[] args) { Animale fido = new Animale();
fido.nome = "aaa"; }}Questa una violazione dell'IH
Non abbiamo adeguatamente nascosto la variabile da modifiche arbitrarie
Java ed i livelli di
Information Hiding (IH)
In Java possibile scegliere chi deve vedere cosa.
I field ed i metodi possono avere differenti livelli di IH
Esistono tre livelli di IH
public tutti possono vedere e/o modificare il field e/o il metodo
protected solo le classi derivare possono vedere e/o modificare il field e/o il metodo
private solo la classe contenente il field e/o il metodo pu accederci
Esiste un quarto livello, package, ma non si utile ai nostri scopi
Diminuiamo la visibilit
class Animale { String nome;
String getNome() { return nome; }
void setNome(String nuovoNome){ nome = nuovoNome; }
}class Animale { private String nome;
String getNome() { return nome; }
void setNome(String nuovoNome){ nome = nuovoNome; }
}Cosa cambia
Con questa piccola modifica la classe xxx non compila pi.Abbiamo impedito modifiche dirette al field 'nome'Anche protected avrebbe nascosto la visibilit.Domanda: Cosa avrebbe fatto invece public?Domanda: Come faccio a cambiare il nome adesso?
Best practices per
l'information hiding
E' pratica diffusa e altamente consigliabile
definire i field sempre private
definire i metodi che devono restituire o impostare lo stato di un field public
definire i metodi che non aggiungono significato all'oggetto come protected o private (ad esempio un metodo che controlla la validit del field 'nome')
Overloading
Abbiamo visto che una classe pu avere pi di un costruttore, purch gli argomenti differiscano per numero oppure per tipo
Questa caratteristica si chiama Overloading
Tutti i metodi, non soltanto i costruttori, possono fare overloading
public class Animale { public void muovi() {
}
public void muovi(double centimetri) {
}}
Esercizi cosa sapere
Cosa sapere per svolgere gli esercizi
Per stampare a video una stringa
System.out.println("hello");
Se ad una stringa non viene assegnato nessun valore, viene impostata a null (null e' una parola riservata Java)
Per avviare una classe inserire il metodo main
public static void main(String[] args) {
}
Esempio
Scrivere la classe Animale contenente il metodo getNome()
Scrivere la classe TestAnimale con il metodo main che stampa il nome di una istanza Animale
public class Animale {
public String getNome() { return "Polly"; }}
public class TestAnimale {
public static void main(String[] args) {Animale animale = new Animale();
System.out.println(animale.getNome());}
}
Esercizio 1
Definire una classe Gatto il cui costruttore prende un nome
Definire una classe Canarino il cui costruttore prende un nome
Definire una classe Fattoria che memorizza il gatto ed il canarino
ha un metodo stampaNomiAnimali che stampa tutti I nomi degli abitanti della fattoria
Definire una classe TestFattoria (con il main) che
Istanzia un gatto di nome "Silvestro" ed un un canarino di nome "Titti"
istanzia una fattoria
Inserisce il gatto ed il canarino nella fattoria
Richiama il metodo stampaNomiAnimali
Usare getters, setters e l'information hiding
Classi Gatto e Canarino
public class Gatto { private String nome;
public Gatto(String nome) { this.nome = nome; }
public String getNome() { return nome; }}
public class Canarino { private String nome; public Canarino(String nome) { this.nome = nome; }
public String getNome() { return nome; }}
Classe Fattoria
public class Fattoria { private Gatto gatto; private Canarino canarino;
public Gatto getGatto() { return gatto; }
public void setGatto(Gatto gatto) { this.gatto = gatto; }
public Canarino getCanarino() { return canarino; }
public void setCanarino(Canarino canarino) { this.canarino = canarino; }
public void stampaNomiAnimali() { System.out.println(gatto.getNome()); System.out.println(canarino.getNome());
}}
Classe testFattoria
public class TestFattoria { public static void main(String[] args) { Gatto gatto = new Gatto("Silvestro"); Canarino canarino = new Canarino("Titti"); Fattoria fattoria = new Fattoria(); fattoria.setGatto(gatto); fattoria.setCanarino(canarino);
fattoria.stampaNomiAnimali(); }}
21/06/08