Lezione di Silvano Natalizi 28 ottobre 2008 Modulo Programmazione Orientata agli Oggetti 4° parte La relazione di Ereditarietà
La guerra delle sedie
In un’azienda di software a due programmatori è affidato il medesimo problema e l’incarico di scrivere il programma. Il capo costringe alla competizione i due programmatori. Promette… a chi arriva per primo a dare una soluzione soddisfacente, …una di quelle sedie che tutte le persone importanti hanno nella silicon Valley!
La specifica del problema
Disegnare un’interfaccia grafica con delle forme geometriche: un quadrato, un cerchio e un rettangolo.
Quando un utente clicca su di una forma, questa deve ruotare in senso orario di 360 gradi
e deve emettere un suono specifico
I due programmatori
Simone è un programmatore procedurale
Pensa: quali sono le cose che deve fare questo programma ? Di quali funzioni ha bisogno ?
ruota e emettiSuono
Per cui si mette a scrivere le due procedure. D’altra parte che cosa è un programma se non una pila di funzioni ?
Matteo è un programmatore Orientato agli Oggetti
Pensa: quali sono gli oggetti di questo programma ?
Le Forme !
Per cui si mette a scrivere le classi degli oggetti. D’altra parte che cosa è un programma se non un insieme di oggetti che si scambiano messaggi ?
I due programmi
ruota(numeroForma) {
// ruota la forma di 360°
}
emettiSuono(numeroForma){
// usa il numero della forma per scegliere il tipo di suono
// suonalo
}
Cerchio Ruota(){ // codice per ruotare } emettiSuono(){ //codice per il suono del cerchio } Triangolo Ruota(){ //Codice per ruotare } emettiSuono(){ //codice per il suono del triangolo } procedurale Orientato agli oggetti
Chi ha vinto la sedia ?
Simone sente si sente già seduto sull’acciaio arrotondato.
Ma…
Un momento c’è stata una variazione nelle specifiche del problema !
Aggiunta alle precedenti specifiche
Implementazione della nuova specifica
Simone si mette al lavoro
La funzione ruota() non deve essere modificata.
Ma emettiSuono(…) deve essere modificata:
emettiSuono(numeroForma){
Se la forma non è un’ameba usa il numeroForma per scegliere la musica e suonala
else
Suona la musica dell’ameba
}
Matteo si mette a ridere, tira fuori la sua penna e scrive una nuova classe:
Ameba Ruota() { //codice per ruotare l’ameba } emettiSuono(){ //codice per emettere la musica dell’ameba }
Non deve modificare il codice già scritto
C’è un errore, il manager dice…
In tono di disappunto, “Oh, no l’ameba non deve ruotare in quel modo:
Entrambi i programmatori hanno scritto il codice per la rotazione in questo modo:
Determina il rettangolo che include la forma
Calcola il centro di quel rettangolo e ruota la forma attorno a quel punto
Ma l’ameba deve ruotare non nel suo centro, ma attorno al suo punto estremo come un pendolo!
Simone, il procedurale procede alla correzione introducendo nella sua procedura ruota() un if/else e codifica la nuova funzione.
Ma il capo “Grosso errore! Onestamente non credi che la specifica possa cambiare di nuovo ?”
Il nuovo codice
Simone, il procedurale
Ruota(numeroForma, x,y){
If la forma non è un’ameba calcola il punto centrale poi ruota
Else
calcola il punto estremo e poi ruota
Matteo modifica il metodo ruota(), ma solo all’interno della classe Ameba! Non tocca affatto il codice della altre classi.
Ha vinto Matteo ?
Simone ha trovato un errore nel codice di Matteo
Hai del codice duplicato !
La procedura ruota() è addirittura in tutte e quattro le classi !
Hai realizzato un disegno poco intelligente
Devi mantenere quattro diversi metodi ruota()!
La risposta di Matteo
Presumo che tu non abbia visto ancora il disegno finale !
Lascia che ti mostri come lavora l’ereditarietà
1) Guardo a cosa hanno in comune le quattro classi
2) esse sono forme e tutte ruotano ed emettono suoni. Pertanto faccio astrazione degli elementi in comune e li inserisco in una nuova classe che chiamo Forma
3) quindi collego le altre quattro classi alla nuova classe “Forma” in una relazione chiamata di ereditarietà.
Critica di Simone
Il problema è che la forma ameba ha una procedura ruota() e emettiSuono() completamente diversa dalle altre forme !
Ma il metodo di ameba come può fare qualcosa di diverso se eredita la sua funzionalità dalla classe “Forma” ?
Matteo: l’ultima fase del lavoro
La forma “Ameba” può avere un suo comportamento diverso perché sovrascrive (overrides) i metodi della classe “Forma”
Pertanto quando qualcuno dice ad Ameba di ruotare, java sa esattamente quale metodo ruota() deve eseguire !
Sovrascrivere significa che una classe ridefinisce uno dei suoi metodi ereditati quando ha bisogno di cambiare o estendere il comportamento di quel metodo.
0 comments
Post a comment