1 / 140

Ereditarietà

Ereditarietà. Concetti principali Ereditarietà e (overriding) di metodi Dynamic dispatch e polimorfismo Ereditarietà e costruttori Livelli di accesso protected e package La classe Object metodi toString , equals e clone. Ereditarietà – introduzione.

Download Presentation

Ereditarietà

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ereditarietà

  2. Concetti principali • Ereditarietà e (overriding) di metodi • Dynamic dispatch e polimorfismo • Ereditarietà e costruttori • Livelli di accesso protected e package • La classe Object • metodi toString, equalseclone

  3. Ereditarietà – introduzione • Un meccanismo per estendere classi con nuovi campi e nuovi metodi • Esempio: dato un conto bancario, vogliamo definire un conto con interessi • SavingsAccount (~ libretto di risparmio) class SavingsAccount extends BankAccount{ nuovi metodi nuovi campi } Continua…

  4. Ereditarietà – introduzione • SavingsAccount eredita automaticamente tutti i metodi e campi di BankAccount • Terminologia • Superclasse = classe che viene estesa (BankAccount) • sottoclasse = classe che estende (Savings) SavingsAccount collegeFund = new SavingsAccount(10); // Conto con il 10% tasso di interesso collegeFund.deposit(500); // Possiamo usare un metodo di BankAccount // anche su oggetti di tipo SavingsAccount Continua…

  5. Superclassi vs interfacce • Estendere una classe è diverso da implementare una interfaccia • Elementi comuni: entrambi i meccanismi generano sottotipi • Istanze di una sottoclasse possono essere assegnate a variabili della superclasse • Istanze di una classe possono essere asseganate a variabili dell’interfaccia che la classe implementa Continua…

  6. Superclassi vs interfacce • Estendere una classe è diverso da implementare una interfaccia • Elementi di differenza: • Estendendo una classe ereditiamo anche il comportamento (l’implementazione dei metodi ed i campi) della superclasse • riuso di codice • È possibile estendere al più una classe (in Java) mentre si possono implementare più interfacce

  7. Diagrammi UML • La relazione di sottoclasse è transitiva • Ogni class estende la classe Object, direttamente o indirettamente

  8. Ereditarietà – introduzione • Nell’implementazione di una sottoclasse definiamo solo i campi aggiuntivi, ed i metodi aggiuntivi o modificati (overridden) public class SavingsAccount extends BankAccount { public SavingsAccount(double rate) { interestRate = rate; } public void addInterest() { double interest = getBalance() * interestRate / 100; deposit(interest); } private double interestRate; } In questo caso solo campi e metodi nuovi

  9. Ereditarietà – introduzione • Encapsulation: la sottoclasse non ha accesso ai campi privati della superclasse • addInterest()invocagetBalance()edeposit()per modificare il saldo • il campobalancenon può essere riferito essendoprivate) • Nota: addInterest() invoca getBalance() senza specificare un oggetto • l’invocazione riguarda this, l’istanza della sottoclasse che eredita anche la struttura della superclasse

  10. Istanze di sottoclasse • Un oggetto di tipo SavingsAccount eredita il campo balance da BankAccount, ed ha un campo aggiuntivo, interestRate:

  11. Sintassi: estensione di classe class SubclassName extends SuperclassName{ metodi    campi } Continua…

  12. Sintassi: estensione di classe Esempio: public class SavingsAccount extends BankAccount { public SavingsAccount(double rate) { interestRate = rate; } public void addInterest() { double interest = getBalance() * interestRate / 100; deposit(interest); } private double interestRate; } Scopo: Definire una nuova classe che eredita da una classe esistente e definisce nuovi metodi e campi.

  13. Domanda • Quali metodi possono essere invocati su oggetti di tipo SavingsAccount?

  14. Risposta • deposit, withdraw, getBalance, e addInterest.

  15. Domanda • Date due classi Manager e Employee, quale delle due definireste come superclasse e quale come sottoclasse?

  16. Risposta • Manager è la sottoclasse; Employee la superclasse

  17. Gerarchie di classi • Le applicazioni sono spesso formate come gerarchie complesse di classi in relazione di ereditarietà • Esempio:

  18. Gerarchie di classi – Swing Continua…

  19. Gerarchie di classi – Swing • La superclasse JComponentdefinisce due metodi getWidth, getHeight ereditati da tutte le classi nella gerarchia • La classe AbstractButton ha metodi set/get per definire e accedere alla etichetta o icona associata al pulsante

  20. Domanda • Quale è lo scopo della classe JTextComponent nella gerarchia Swing?

  21. Risposta • Rappresenta gli aspetti comuni del comportamento delle classi JTextField e JTextArea

  22. Una gerarchia di conti bancari • Progettiamo una applicazione per una banca che voglia offrire ai suoi clienti due tipi di conti bancari: • Checking account: non offre interessi, ma permette un numero di transazioni gratuite e per le altre commissioni basse • Savings Account: interessi calcolati su base mensile e transazioni con commissione Continua…

  23. Una gerarchia di conti bancari Continua…

  24. Una gerarchia di conti bancari • Tutti i tipi di conto offrono il metodo getBalance() • Tutti i tipi di conto offrono deposit()e withdraw(), • Implementazione diversa nei diversi tipi • CheckingAccount include un metodo deductFees() per dedurre le commissioni • SavingsAccount include un metodo addInterest() per il calcolo degli interessi

  25. Ereditarietà – metodi • Tre scelte possibili nel progetto di una sottoclasse • ereditare i metodi della superclasse • modificare i metodi della superclasse (overriding) • definire nuovi metodi / nuove versioni dei metodi ereditati (overloading) Continua…

  26. Ereditarietà – metodi ereditati • Metodi della superclasse visibili nella sottoclasse • Non ridefiniti nella sottoclasse • I metodi della superclasse possono essere sempre invocati su oggetti della sottoclasse • Quando invocati su oggetti della sottoclasse this punta all’oggetto della sottoclasse • Il tipo di this cambia, a seconda dell’oggetto a cui this viene legato Continua…

  27. Ereditarietà – metodi aggiuntivi • Le sottoclassi possono definire nuovi metodi, non definiti nella superclasse • I nuovi metodi sono invocabili solo su oggetti della sottoclasse

  28. Ereditarietà – overriding di metodi • Forniscono una implementazione diversa di un metodo che esiste nella superclasse • Il metodo nella sottoclasse deve avere la stessa firma del metodo nella superclasse • stesso nome/tipo risultato, stessi tipi dei parametri, • livello di accesso maggiore o uguale • Deve anche soddisfare lo stesso contratto (vedremo …) Continua…

  29. Ereditarietà – overriding di metodi • Invocazione basata su dispatch dinamico • Se diretto ad un oggetto della sottoclasse, un messaggio invoca sempre il metodo della sottoclasse (come ci si aspetta) Continua…

  30. Domanda • Date le due dichiarazioni • Quali dei seguenti comandi compilano correttamente? Per quelli che compilano quale è l’effetto dell’esecuzione? CheckingAccount c = new CheckingAccount(10); SavingsAccount s = new SavingsAccount(); BankAccount b1 = c; BankAccount b2 = s; b1.deductFees(); c.deductFees(); s.deductFees(); ((CheckingAccount)b1).deductFees(); b1 = b2; ((CheckingAccount)b1).deductFees(); Continued…

  31. Risposta CheckingAccount c = new CheckingAccount(10); SavingsAccount s = new SavingsAccount(); BankAccount b1 = c; // compila, esegue l’assegnamento BankAccount b2 = s; // compila, esegue l’assegnamento b1.deductFees(); // errore di compilazione c.deductFees(); // compila, invoca il metodo s.deductFees(); // errore di compilazione // compila, esegue il metodo ((CheckingAccount)b1).deductFees(); b1 = b2; // compila, esegue l’assegnamento // compila ma ClassCastException in esecuzione ((CheckingAccount)b1).deductFees();

  32. Ereditarietà – variabili di istanza • Tutti i campi di una superclasse sono automanticamente ereditati nella sottoclasse • Ma non necessariamente possono essere acceduti direttamente dalla sottoclasse! • La sottoclasse può definire campi che non esistono nella superclasse Continua…

  33. Ereditarietà – variabili di istanza • Nel caso di collisione di nomi … • La definizione del campo della sottoclasse maschera quella del campo nella superclasse • Collisioni di nomi legali ma decisamente inopportune (… vedremo)

  34. La classe CheckingAccount • Sovrascrive (overrides) i metodi deposit()e withdraw() per incrementare il contatore delle operazioni: public class CheckingAccount extends BankAccount { public void deposit(double amount) {. . .} public void withdraw(double amount) {. . .} public void deductFees() {. . .} // nuovo metodo private int transactionCount; // nuovo campo} Continua…

  35. La classe CheckingAccount • due variabili di istanza: • Balance, ereditato daBankAccount • transactionCount, nuovo Continua…

  36. La classe CheckingAccount • Quattro metodi • getBalance() • ereditato daBankAccount • deposit(double amount) • sovrascrive il metodo corrispondente diBankAccount • withdraw(double amount) • sovrascrive il metodo corrispondente diBankAccount • deductFees() • nuovo

  37. Accesso ai campi della superclasse • Consideriamo il metodo deposit() della classe CheckingAccount public void deposit(double amount) { transactionCount++; // aggiungi amount a balance . . . } Continua…

  38. Accesso ai campi della superclasse • Consideriamo il metodo deposit() della classe CheckingAccount • Non possiamo modificare direttamente balance • balanceè un campo privato della superclasse public void deposit(double amount) { transactionCount++; // aggiungi amount a balance balance += amount;// ERRORE!} Continua…

  39. Accesso ai campi della superclasse • Una sottoclasse non ha accesso ai campi / metodi private della superclasse • Deve utilizzare l’interfaccia public (o protected vedremo …) della superclasse • Nel caso in questione, CheckingAccount deve invocare il metodo deposit() della superclasse

  40. Accesso ai campi della superclasse • Errore tipico: aggiungiamo un nuovo campo con lo stesso nome: public class CheckingAccount extends BankAccount { public void deposit(double amount) { transactionCount++; balance = balance + amount; } . . . private double balance; // Brutta idea!} Continua…

  41. Accesso ai campi della superclasse • Ora il metodo deposit compila correttamente ma non modifica il saldo corretto! Continua…

  42. Accesso ai campi della superclasse • Soluzione, accediamo i campi della superclasse via i metodi della stessa superclasse public class CheckingAccount extends BankAccount { public void deposit(double amount) { transactionCount++; balance = balance + amount; deposit(amount); } . . . } Continua…

  43. Chiamata di un metodo overridden • Non possiamo invocare direttamente deposit(amount) …. • È come invocare this.deposit(amount) class CheckingAccount public { . . . void deposit(double amount) { transactionCount++; balance = balance + amount; deposit(amount); // questo è un loop! } . . . } Continua…

  44. Chiamata di un metodo overridden • Dobbiamo invece invocare il metodo deposit() della superclasse • Invochiamo via super public void deposit(double amount) { transactionCount++; balance = balance + amount; super.deposit(amount); }

  45. Sintassi: chiamata via super super.methodName(parameters) Esempio:  public void deposit(double amount){   transactionCount++;   super.deposit(amount);} Scopo: Invocare un metodo overridden della superclasse

  46. La classe CheckingAccount public class CheckingAccount extends BankAccount { . . . public void withdraw(double amount) { transactionCount++; // sottrai amount da balance super.withdraw(amount); } Continua…

  47. La classe CheckingAccount • Definizione dei metodi aggiuntivi public void deductFees() { if (transactionCount > FREE_TRANSACTIONS) { double fees = TRANSACTION_FEE * (transactionCount - FREE_TRANSACTIONS); super.withdraw(fees); } transactionCount = 0; } . . . private static final int FREE_TRANSACTIONS = 3; private static final double TRANSACTION_FEE = 2.0;}

  48. Domanda • Perchè il metodo withdraw() nella classe CheckingAccount invoca super.withdraw()? • È possibile invocare un metodo della supeclasse senza utilizzare il riferimento super? • Perchè il metodo deductFees() nella classe CheckingAccount invoca super.withdraw()?

  49. Risposte • Perché deve modificare la variabile balance e non può farlo direttamente in quanto è privata della superclasse n • Si se la sottoclasse non ridefinisce il metodo • Per evitare che il prelievo dell’importo delle commissioni venga contato come operazione.

  50. Costruttori di sottoclasse • Il costruttore di una sottoclasse provvede ad inizializzare la struttura delle istanze della sottoclasse • Come abbiamo visto, questa include la parte definita nella superclasse • Per inizializzare i campi privati della superclasse invochiamo il costruttore della superclasse Continua…

More Related