Obiettivi Capitolo 10 Ereditarietà Imparare cos’è l’ereditarietà | Capire come ereditare e sovrascrivere i metodi superclasse | Invocare il costruttore della superclasse | I controlli d’eccesso protected e package | La superclasse Object e i metodi toString e equals | Fondamenti Informatica Introduzione all’ereditarietà Ereditarietà z | estendere classi aggiungendo metodi e campi // Savings account with 10% interest collegeFund.deposit(500); // OK to use BankAccount method with SavingsAccount object Classe estesa = Superclasse (BankAccount), | Classe che estende = Sottoclasse (Savings) | class SavingsAccount extends BankAccount { new methods new instance fields } UNIPD 2007 SavingsAccount automaticamente eredita metodi e le istanze di BankAccount SavingsAccount collegeFund = new SavingsAccount(10); Es: conto di risparmio = Conto corrente bancario con interessi Fondamenti Informatica 2 Introduzione all’ereditarietà | | UNIPD 2007 3 Fondamenti Informatica UNIPD 2007 4 1 Introduzione all’ereditarietà | Ereditare da una classe ≠ implementare interfaccia z | Diagramma dell’ereditarietà | la sottoclasse eredita comportamento e stato Un vantaggio dell’ereditarietà è il riutilizzo di codice Fondamenti Informatica UNIPD 2007 5 Ogni classe estende la classe Object direttamente o indirettamente Fondamenti Informatica Introduzione all’ereditarietà | UNIPD 2007 6 Introduzione all’ereditarietà Sottoclasse specifica le istanze aggiunte, i metodi aggiunti, e i metodi modificati o riscritti | Incapsulamento z public class SavingsAccount extends BankAccount { public SavingsAccount(double rate) { interestRate = rate; } public void addInterest() { double interest = getBalance() * interestRate / 100; deposit(interest); } z | addInterest chiama getBalance non può aggiornare il campo balance della superclasse (xché il campo è private) Nota che addInterest chiama getBalance senza specificare un parametro implicito (la chiamata si applica allo stesso oggetto) private double interestRate; Fondamenti Informatica } UNIPD 2007 7 Fondamenti Informatica UNIPD 2007 8 2 Layout di un oggetto Sottoclasse | Sintassi 10.1: Ereditarietà L’oggetto SavingsAccount eredita l’istanza di balance da BankAccount, e guadagna un’altra istanza: interestRate Fondamenti Informatica UNIPD 2007 9 class SubclassName extends SuperclassName { methods instance fields } Fondamenti Informatica Sintassi 10.1: Ereditarietà UNIPD 2007 Verifica Example: public class SavingsAccount extends BankAccount { public SavingsAccount(double rate) { interestRate = rate; } public void addInterest() { double interest = getBalance() * interestRate / 100; deposit(interest); } private double interestRate; } 1. Quale campo istanza ha un oggetto della classe SavingsAccount? 2. Elencare i 4 metodi che puoi applicare all’oggetto SavingsAccount Se la classe Manager estende la classe Employee, qual’è la Superclasse e quale la Sottoclasse? 3. Purpose: To define a new class that inherits from an existing class, and define the methods and instance fields that are added in the new class. Fondamenti Informatica UNIPD 2007 10 11 Fondamenti Informatica UNIPD 2007 12 3 Risposte 1. 2. 3. Gerarchie dell’ereditarietà due istanze: balance e interestRate deposit, withdraw, getBalance, e addInterest. Manager è la Sottoclasse; Employee è la Superclasse. Fondamenti Informatica UNIPD 2007 13 | Un insieme di classi può formare una complessa gerarchia di ereditarietà Fondamenti Informatica Gerarchie dell’ereditarietà es: Swing UNIPD 2007 14 Gerarchie dell’Ereditarietà es: gerarchia Swing Superclasse JComponent ha i metodi getWidth, getHeight | La classe AbstractButton ha i metodi per impostare/prendere testo e icone | Fondamenti Informatica UNIPD 2007 15 Fondamenti Informatica UNIPD 2007 16 4 Una semplice gerarchia: es. conto corrente | Una semplice gerarchia: es. conto corrente Considera una banca che offre ai suoi clienti i seguenti tipi di conto: 1. 2. Conto corrente: no interessi; poche transazioni gratuite al mese, alle successive transazioni hanno una piccola spesa Conto risparmio: si guadagna l’interesse che viene composto mensilmente Fondamenti Informatica UNIPD 2007 17 Fondamenti Informatica Una semplice gerarchia: es. conto corrente Superclasse JComponent ha i metodi getWidth, getHeight | La classe AbstractButton ha i metodi per impostare/prendere testo e icone UNIPD 2007 18 Una semplice gerarchia: es. conto corrente Tutti i conti hanno il metodo getBalance | Tutti i conti supportano i metodi deposit e withdraw, ma l’implementazione è diversa | Fondamenti Informatica UNIPD 2007 | 19 | Al conto corrente serve il metodo deductFees; | Al Conto risparmio serve il metodo addInterest Fondamenti Informatica UNIPD 2007 20 5 Verifica Risposte 4. Qual’è lo scopo della classe JTextComponent in Fig. 4? 5. Quale istanza dovremo aggiungere alla classe CheckingAccount? Fondamenti Informatica UNIPD 2007 4. 5. 21 Per esprimere il comportamento comune del campo testo e delle componenti del testo Ci serve un contatore che conti il numero di prelievi e depositi Fondamenti Informatica Ereditarietà - metodi | Ereditarietà - metodi Sovrascrivere un metodo: | fornire una diversa implementazione del metodo che esiste nella Superclasse z Deve avere la stessa firma (stesso nome e stessi tipi di parametri) z Se è applicato a un oggetto di tipo Sottoclasse, il metodo sovrascritto viene eseguito UNIPD 2007 Ereditare un metodo: Non fornire una diversa implementazione del metodo che esiste nella Superclasse z Il metodo della Superclasse può venire applicato all’oggetto Sottoclasse z Fondamenti Informatica 22 UNIPD 2007 z 23 Fondamenti Informatica UNIPD 2007 24 Continued… 6 Ereditarietà - metodi | Ereditare campi d’istanza Aggiungere un metodo: Non si possono riscrivere campi | Ereditare campi : tutti i campi della Superclasse vengono automaticamente ereditati | Aggiungere campi: scrivere un nuovo campo che non esiste nella Superclasse | Fornire un nuovo metodo che non esiste nella Superclasse z Il nuovo metodo può essere applicato solo agli oggetti Sottoclasse z Fondamenti Informatica UNIPD 2007 25 Fondamenti Informatica E se definisci un nuovo campo d’istanza con lo stesso nome del campo della Superclasse? | UNIPD 2007 sovrascrivere deposit e withdraw per incrementare il contatore delle transazioni public class CheckingAccount extends BankAccount { public void deposit(double amount) {. . .} public void withdraw(double amount) {. . .} public void deductFees() {. . .} // new method private int transactionCount; // new instance field } Ogni oggetto avrebbe due istanze con lo stesso nome z I campi possono avere valori diversi z Possibile ma estremamente indesiderabile z Fondamenti Informatica 26 Implementare la classe CheckingAccount Ereditare campi d’istanza | UNIPD 2007 27 Fondamenti Informatica UNIPD 2007 28 7 Implementare la classe CheckingAccount | Implementare la classe CheckingAccount Ogni oggetto CheckingAccount ha due istanze: | balance (ereditato da BankAccount) z transactionCount (nuovo a CheckingAccount) getBalance() (ereditato da BankAccount) z deposit(double amount) (sovrascrive il metodo di BankAccount) z withdraw(double amount) (sovrascrive il metodo di BankAccount) z deductFees() (nuovo a CheckingAccount) z Fondamenti Informatica UNIPD 2007 Puoi applicare 4 metodi all’oggetto CheckingAccount: z 29 Fondamenti Informatica I campi ereditati sono privati | Considera il metodo deposit di CheckingAccount UNIPD 2007 30 I campi ereditati sono privati una Sottoclasse non ha accesso ai campi privati della sua Superclasse | la Sottoclasse deve usare l’interfaccia pubblica | public void deposit(double amount) { transactionCount++; // now add amount to balance . . . } non può aggiungere amount a balance | balance è un campo private della Superclasse | Fondamenti Informatica UNIPD 2007 31 Fondamenti Informatica UNIPD 2007 32 8 Invocare un metodo Superclasse | Invocare un metodo Superclasse Non si può chiamare deposit(amount) nel metodo deposit di CheckingAccount z Ora chiama il metodo deposito della classe BankAccount | Completa il metodo: | this.deposit(amount) Chiamerebbe lo stesso metodo (ricorsione infinita) | invece, invoca il metodo della Superclasse public void deposit(double amount) { transactionCount++; // Now add amount to balance super.deposit(amount); } | z super.deposit(amount) Fondamenti Informatica UNIPD 2007 33 Sintassi 10.2: invocare un metodo Superclasse Fondamenti Informatica UNIPD 2007 34 Implementazione metodi rimanenti super.methodName(parameters) Example: public void deposit(double amount) { transactionCount++; super.deposit(amount); } Purpose: To call a method of the superclass instead of the method of the current class Fondamenti Informatica UNIPD 2007 35 public class CheckingAccount extends BankAccount { . . . public void withdraw(double amount) { transactionCount++; // Now subtract amount from balance super.withdraw(amount); } Fondamenti Informatica UNIPD 2007 36 9 Implementazione metodi rimanenti Verifica 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; Perchè il metodo withdraw della classe CheckingAccount chiama super.withdraw? Perchè il metodo deductFees imposta il contatore delle transazioni a zero? 6. 7. } Fondamenti Informatica UNIPD 2007 37 Fondamenti Informatica UNIPD 2007 38 Errori comuni: i campi istanza oscuri Risposte 6. Gli serve per ridurre il saldo, e non può accedere al campo balance direttament | 7. In modo che il contatore possa riflettere il numero di transazioni del mese seguente | una Sottoclasse non ha accesso al campo d’istanza privato della Superclasse Errore del principiante: “risolvere" questo problema aggiungendo un’altra istanza con lo stesso nome: public class CheckingAccount extends BankAccount { public void deposit(double amount) { transactionCount++; balance = balance + amount; } . . . private double balance; // Don't Fondamenti Informatica UNIPD 2007 39 } Fondamenti Informatica UNIPD 2007 40 10 Errori comuni: i campi istanza oscuri | Costruttore della Sottoclasse Ora il metodo deposit compila, ma non aggiorna il saldo corretto! | super segiuto dalle parentesi indica una chiamata al costruttore della Superclasse public class CheckingAccount extends BankAccount { public CheckingAccount(double initialBalance) { // Construct superclass super(initialBalance); // Initialize transaction count transactionCount = 0; } . . . } Fondamenti Informatica UNIPD 2007 41 Costruttore della Sottoclasse deve essere la prima istruzione nel costruttore della Sottoclasse | se il costruttore della Sottoclasse non chiama il costruttore della Superclasse, viene usato il costruttore di default della Superclasse | 42 Sintassi 10.1: chiamare il Costruttore della Sottoclasse Example: public CheckingAccount(double initialBalance) { super(initialBalance); transactionCount = 0; } costruttore di default Ö senza parametri z Se tutti i costruttori della Superclasse richiedono parametri, il compilatore dà errore UNIPD 2007 UNIPD 2007 ClassName(parameters) { super(parameters); . . . } z Fondamenti Informatica Fondamenti Informatica Purpose: To invoke a constructor of the superclass. Note that this statement must be the first statement of the subclass constructor. 43 Fondamenti Informatica UNIPD 2007 44 11 Verifica 8. 9. Risposte Perchè il costruttore SavingsAccount nella Sezione 13.1 non chiama il costruttore della Superclasse? Quando invochi un metodo Superclasse con la parola-chiave super, la chiamata deve essere la prima istruzione del metodo della Sottoclasse? Fondamenti Informatica UNIPD 2007 8. 9. 45 Era pronto per usare il costruttore di default della Superclasse, che setta il saldo a zero. No – è un requisito solo dei costruttori. Per esempio, il metodo SavingsAccount.deposit prima incremente il contatore della transazione, poi chiama il metodo della Superclasse. Fondamenti Informatica Conversione di tipo fra sottoclasse e superclasse | | La superclasse anAccount non conosce tutta la storia dell’oggetto a cui si riferisce: anAccount.deposit(1000); // OK anAccount.addInterest(); // No,non è un metodo della classe a cui appartiene anAccount | Quando convertite un oggetto della sottoclasse in un oggetto di superclasse: z z UNIPD 2007 46 Conversione di tipo fra sottoclasse e superclasse I tre riferimenti a oggetti memorizzati in collegeFund, anAccount, e anObject si riferiscono tutti allo stesso oggetto di tipo SavingsAccount Fondamenti Informatica UNIPD 2007 47 Il valore di riferimento stesso non cambia: si tratta dell’indirizzo di memoria che contiene l’oggetto. Ma,dopo la conversione si hanno minori informazioni sull’oggetto. Fondamenti Informatica UNIPD 2007 48 12 Conversione di tipo fra sottoclasse e superclasse | Conversione di tipo fra sottoclasse e superclasse Perchè avere meno informazioni a proposito di un oggetto? z public void transfer(double amount, BankAccount other) { withdraw(amount); other.deposit(amount); } | Potete utilizzare questo metodo per trasferire denaro da ogni tipo di BankAccount Fondamenti Informatica UNIPD 2007 49 Conversione di tipo fra sottoclasse e superclasse | | Questo cast però può essere pericoloso: se vi sbagliate viene lanciata un’eccezione Fondamenti Informatica UNIPD 2007 50 Esempio: if (anObject instanceof BankAccount) { BankAccount anAccount = (BankAccount) anObject; . . . } if (anObject instanceof BankAccount) { BankAccount anAccount = (BankAccount) anObject; . . . } UNIPD 2007 BankAccount anAccount = (BankAccount) anObject; object instanceof TypeName testa se l’oggetto appartiene ad un particolare tipo Fondamenti Informatica Può darsi che abbiate bisogno di convertire un riferimento di superclasse in un riferimento di sottoclasse Syntax 10.4: L’operatore InstanceOf L’operatore instanceof z | per riutilizzare codice che può elaborare oggetti della superclasse ma non oggetti della sottoclasse Obiettivo: Restituisce true se oggetto è un esemplare di TypeName (o di uno dei suoi sottotipi); altrimenti restituisce false. 51 Fondamenti Informatica UNIPD 2007 52 13 Verifica Risposte 10. Perchè il secondo parametro del metodo transfer deve essere di tipo BankAccount e non, per esempio, di tipo SavingsAccount? 11. Perchè non possiamo modificare il secondo parametro del metodo transfer in modo che sia di tipo Object? Fondamenti Informatica UNIPD 2007 53 10. Noi vogliamo usare il metodo per tutti I generi di bank accounts. Noi abbiamo utilizzato un parametro di tipo SavingsAccount, noi perciò non possiamo chiamare il metodo con un oggetto CheckingAccount . 11. Noi non possiamo invocare il metodo deposit di una variabile di tipo Object. Fondamenti Informatica Polimorfismo | UNIPD 2007 54 Polimorfismo In Java il tipo di una variabile non determina completamente il tipo dell’oggetto a cui essa fa riferimento | Il compilatore deve controllare che solo i metodi autorizzati siano stati invocati BankAccount aBankAccount = new SavingsAccount(1000); // aBankAccount holds a reference to a SavingsAccount | Object anObject = new BankAccount(); anObject.deposit(1000); // Wrong! Le chiamate al metodo sono determinate dal tipo reale dell’oggetto, non in base al tipo di riferimento dell’oggetto BankAccount anAccount = new CheckingAccount(); anAccount.deposit(1000); // Calls "deposit" from CheckingAccount Fondamenti Informatica UNIPD 2007 55 Fondamenti Informatica UNIPD 2007 56 14 Polimorfismo | Polimorfismo z | AccountTester.java capacità di riferirsi agli oggetti di vario tipo variandone il comportamento Realizzazione di un polimorfismo: public void transfer(double amount, BankAccount other) { withdraw(amount); // abbreviazione: this.withdraw(amount) other.deposit(amount); } | In relazione ai tipi di oggetti, vengono invocate versioni diverse dei withdraw e deposit Fondamenti Informatica UNIPD 2007 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 57 /** Questo programma collauda la classe BankAccount e le sue sottoclassi. */ public class AccountTester { public static void main(String[] args) { SavingsAccount momsSavings = new SavingsAccount(0.5); CheckingAccount harrysChecking = new CheckingAccount(100); momsSavings.deposit(10000); Fondamenti Informatica AccountTester.java [2] 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: } 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: momsSavings.transfer(1000, harrysChecking); harrysChecking.withdraw(400); // Simulazione della fine del mese momsSavings.addInterest(); harrysChecking.deductFees(); System.out.println("Mom's savings balance = $“ + momsSavings.getBalance()); System.out.println("Harry's checking balance = $“ + harrysChecking.getBalance()); } UNIPD 2007 58 BankAccount.java momsSavings.transfer(2000, harrysChecking); harrysChecking.withdraw(1500); harrysChecking.withdraw(80); Fondamenti Informatica UNIPD 2007 59 /** Un conto bancario ha un saldo che può essere modificato con versamenti e prelievi. */ public class BankAccount { /** Costruisce un conto bancario con saldo uguale a zero. */ public BankAccount() { balance = 0; } /** Costruisce un conto bancario con un saldo assegnato. @param initialBalance il saldo iniziale */ Fondamenti Informatica UNIPD 2007 60 15 BankAccount.java [2] BankAccount.java [2] 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: public BankAccount(double initialBalance) { balance = initialBalance; } /** Versa denaro nel conto bancario. @param amount la somma da versare */ public void deposit(double amount) { balance = balance + amount; } /** Preleva denaro dal conto bancario. @param amount la somma da prelevare */ Fondamenti Informatica UNIPD 2007 61 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: public void withdraw(double amount) { balance = balance - amount; } /** Restituisce il valore del saldo del conto bancario. @return il saldo attuale */ public double getBalance() { return balance; } /** Trasferisce denaro dal conto a un altro conto @param amount la somma da trasferire @param other l’altro conto */ Fondamenti Informatica BankAccount.java [2] 56: 57: 58: 59: 60: 61: 62: 63: } private double balance; UNIPD 2007 62 CheckingAccount.java public void transfer(double amount, BankAccount other) { withdraw(amount); other.deposit(amount); } Fondamenti Informatica UNIPD 2007 63 01: 02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: 18: /** Un conto corrente che addebita commissioni per le transazioni. */ public class CheckingAccount extends BankAccount { /** Costruisce un conto corrente con un saldo assegnato. @param initialBalance il saldo iniziale */ public CheckingAccount(double initialBalance) { // costruisce la superclasse super(initialBalance); // azzerra il conteggio delle transazioni transactionCount = 0; } Fondamenti Informatica UNIPD 2007 64 16 CheckingAccount.java [2] 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: CheckingAccount.java [3] public void deposit(double amount) { transactionCount++; // ora aggiungi amount al saldo super.deposit(amount); } 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: } public void withdraw(double amount) { transactionCount++; // ora sottrai amount dal saldo super.withdraw(amount); } /** Sottrae le commissioni accumulate e azzerra il relativo conteggio. */ Fondamenti Informatica UNIPD 2007 65 08: 09: 10: 11: 12: 13: 14: 15: 16: 17: private int transactionCount; private static final int FREE_TRANSACTIONS = 3; private static final double TRANSACTION_FEE = 2.0; Fondamenti Informatica UNIPD 2007 66 SavingsAccount.java [2] SavingsAccount.java 01: 02: 03: 04: 05: 06: 07: public void deductFees() { if (transactionCount > FREE_TRANSACTIONS) { double fees = TRANSACTION_FEE * (transactionCount - FREE_TRANSACTIONS); super.withdraw(fees); } transactionCount = 0; } /** Un conto bancario che matura interessi a un tasso fisso. */ public class SavingsAccount extends BankAccount { /** Costruisce un conto bancario con un tasso di interesse assegnato. @param rate il tasso di interesse */ public SavingsAccount(double rate) { interestRate = rate; } 18: 19: 20: 21: 22: 23: 24: 25: } public void addInterest() { double interest = getBalance() * interestRate / 100; deposit(interest); } private double interestRate; /** aggiunge al saldo del conto gli interessi maturati. */ Fondamenti Informatica UNIPD 2007 67 Fondamenti Informatica UNIPD 2007 68 17 SavingsAccount.java [3] Verifica Visualizza: Se a è una variabile di tipo BankAccount che contiene un riferimento non nullo, che informazioni abbiamo in merito all’oggetto a cui si riferisce? Se a si riferisce a un conto corrente, che effetto ha l’invocazione seguente? a.transfer(1000, a) 12. Mom's savings balance = $7035.0 Harry's checking balance = $1116.0 13. Fondamenti Informatica UNIPD 2007 69 Fondamenti Informatica Risposte 12. 13. UNIPD 2007 70 Controllo di accesso L’oggetto è un’istanza di BankAccount o di una delle sue sottoclassi. Il bilancio di a è invariato, e la transazione count viene incrementata due volte. | Java fornisce quattro livelli per il controllo di accesso a variabili, metodi e classi: z public access • Accesso dai metodi di tutte le classi z private access • Accesso solamente mediante i metodi della loro classe specifica z protected access • Accesso dai metodi di tutte le sottoclassi Argomenti avanzati 10.3 Fondamenti Informatica UNIPD 2007 71 Fondamenti Informatica UNIPD 2007 72 18 Livelli di accesso raccomandato Controllo di accesso | package access | Default in assenza di un modificatore di accesso z Si può accedere da tutte le classi dello stesso pacchetto z Buona impostazione per le classi, ma estremamente infelice per i campi z Fondamenti Informatica UNIPD 2007 Variabili di istanza e campi static: sono sempre private. Eccetto: z z z 73 Fondamenti Informatica Livelli di accesso raccomandato Metodi: public o private | Classi o interfacce: public o package La migliore alternativa al package access (accesso di pacchetto): inner classes (classi interne) • In generale, l’inner classes (classi interne) non può essere pubblica (esiste qualche eccezione, ad es.Ellipse2D.Double) | Bisogna stare attenti ad utilizzare i metodi con il package access (generalmente i metodi dovrebbero essere public o private) 75 Fondamenti Informatica UNIPD 2007 UNIPD 2007 74 Verifica | z Le costanti pubbliche(public static final) sono utili e sicure. Qualche oggetto, come System.out, ha bisogno di essere accessibile a tutti i programmi (public) In rare occasioni, alcune classi in un pacchetto devono cooperare molto strettamente;può essere utile fornire ad alcune variabili il package access(accesso di pacchetto). Tuttavia le inner classes( classi interne) sono la soluzione migliore. 14. 15. Quale è una comune motivzione che porta alla definizione di campi di esemplare con package access(accesso di pacchetto)? Se una classe dotata di costruttore pubblico ha il package access, che ne può costruire esemplari? Fondamenti Informatica UNIPD 2007 76 19 Object:La superclasse universale Risposte Accidentalmente si dimentica il modificatore private. Qualsiasi metodo di classe nello stesso pacchetto. 14. 15. Fondamenti Informatica UNIPD 2007 | Tutte le classi estendono automaticamente la classe Object 77 Fondamenti Informatica Object:La superclasse universale | z z | 78 Sovrascrivere il metodo toString I metodi più utilizzati: z UNIPD 2007 Restituisce una stringa per ciascun oggetto | Utile per trovare errori logici: | String toString() boolean equals(Object otherObject) Object clone() Rectangle box = new Rectangle(5, 10, 20, 30); String s = box.toString(); // Sets s to "java.awt.Rectangle[x=5,y=10,width=20,height=30]" Una buona idea è quella di sovrascrivere questi metodi nelle vostre classi Fondamenti Informatica UNIPD 2007 79 Fondamenti Informatica UNIPD 2007 80 20 Sovrascrivere il metodo toString | Sovrascrivere il metodo toString toString chiamato tutte le volte che concatenate una stringa con un oggetto. | "box=" + box; // risulta: "box=java.awt.Rectangle[x=5,y=10,width=20,height=30]" | public String toString() { return "BankAccount[balance=" + balance + "]"; } Object.toString stampa il nome della classe seguito dal codice hash dell’oggetto | BankAccount momsSavings = new BankAccount(5000); String s = momsSavings.toString(); // s si riferisce a qualcosa di simile a UNIPD 2007 81 Fondamenti Informatica Sovrascrivere il metodo equals | | UNIPD 2007 UNIPD 2007 82 Sovrascrivere il metodo equals equals confronta il contenuto di due oggetti: Fondamenti Informatica Questo sistema funziona meglio: BankAccount momsSavings = new BankAccount(5000); String s = momsSavings.toString(); // s si riferisce alla stringa "BankAccount[balance=5000]" "BankAccount@d24606bf" Fondamenti Informatica Per una informazione migliore dell’oggetto, si sovrascrive il metodo toString: 83 L’opeatore == verifica se due riferimenti puntano allo stesso oggetto: Fondamenti Informatica UNIPD 2007 84 21 Sovrascrivere il metodo equals | Definite il metodo equals per verificare se due Sovrascrivere il metodo equals oggetti hanno lo stesso stato. | Quando ridefinite il metodo, non vi è permesso modificare la firma del metodo stesso, dovete eseguire un cast sul parametro: | Dovreste sovrascrivere anche il metodo hashCode, in modo che oggetti uguali abbiano lo stesso codice hash. public class Coin { . . . public boolean equals(Object otherObject) { Coin other = (Coin) otherObject; return name.equals(other.name) && value == other.value; } . . . } Fondamenti Informatica UNIPD 2007 85 Fondamenti Informatica Verifica 16. 17. 86 Risposte L’invocazione x.equals(x) deve sempre restituire true? Si può realizzare il metodo equals usando il metodo toString? E’ una cosa consigliabile? Fondamenti Informatica UNIPD 2007 UNIPD 2007 16. 17. 87 Certo,a meno che x non sia null. Se al metodo toString ritorna una stringa che descriva tutte le istanze, si invoca semplicemente il metodo toString nei parametri impliciti ed espliciti, e appare il risultato. Tuttavia, confrontare i campi di un oggetto risulta più efficiente di convertirli in stringhe. Fondamenti Informatica UNIPD 2007 88 22 Sovrascrivere il metodo clone | Sovrascrivere il metodo clone La copia di un riferimento a un oggetto fornisce semplicemente due riferimenti allo stesso oggetto | Creare copia oggetto BankAccount account2 = account; Fondamenti Informatica UNIPD 2007 89 Fondamenti Informatica Sovrascrivere il metodo clone UNIPD 2007 90 Il metodo Object.clone Definire il metodo clone significa realizzare un nuovo oggetto | Come invocare il metodo clone: | | Crea sotto copie BankAccount clonedAccount = (BankAccount) account.clone(); | Deve restituire un valore perché è di tipo Object Fondamenti Informatica UNIPD 2007 91 Fondamenti Informatica UNIPD 2007 92 23 Il metodo Object.clone Non clona automaticamente tutti i sottooggetti | Il metodo viene dichiarato protected; questo vi impedisce di chamare x.clone() se la classe a cui appartiene x non ha ridefinito clone come metodo public | Bisogna sovrascrivere il metodo clone con cura | Fondamenti Informatica UNIPD 2007 93 24