• Non ci sono risultati.

Ereditarietà Ereditarietà

N/A
N/A
Protected

Academic year: 2021

Condividi "Ereditarietà Ereditarietà"

Copied!
75
0
0

Testo completo

(1)

Ereditarietà Ereditarietà

C. Horstmann

C. Horstmann

Fondamenti di programmazione e Java 2

Fondamenti di programmazione e Java 2

3^ edizione Apogeo

3^ edizione Apogeo

trad. Nicola Fanizzi

trad. Nicola Fanizzi

corso di Programmazione, CdS: Informatica TPS

corso di Programmazione, CdS: Informatica TPS

Dip. di Informatica, Università degli studi di Bari

Dip. di Informatica, Università degli studi di Bari

(2)

2 2

Obiettivi Obiettivi

 Conoscere il concetto di ereditarietà Conoscere il concetto di ereditarietà

 Capire come ereditare e sovrascrivere metodi di Capire come ereditare e sovrascrivere metodi di superclassi

superclassi

 Saper chiamare costruttori di superclassi Saper chiamare costruttori di superclassi

 Conoscere il controllo d'accesso Conoscere il controllo d'accesso protected protected e e package

package

 Capire la superclasse comune Capire la superclasse comune Object Object e e sovrascrivere i suoi metodi

sovrascrivere i suoi metodi toString toString e e equals equals

(3)

3 3

Introduzione all'Ereditarietà Introduzione all'Ereditarietà

Ereditarietà Ereditarietà : :

estendere le classi aggiungendo campi e metodi estendere le classi aggiungendo campi e metodi

 Esempio: Esempio:

Conto Risparmio = Conto corrente con interessi Conto Risparmio = Conto corrente con interessi

class SavingsAccount extends BankAccount class SavingsAccount extends BankAccount { {

new methods new methods

new instance fields new instance fields }}

(4)

4 4

Introduzione all'Ereditarietà Introduzione all'Ereditarietà

 SavingsAccount SavingsAccount eredita automaticamente eredita automaticamente tutti i metodi e campi d'istanza di

tutti i metodi e campi d'istanza di BankAccount BankAccount

 Classe che viene estesa = Classe che viene estesa = superclasse superclasse ( ( BankAccount BankAccount ) )

 Classe che estende = Classe che estende = sottoclasse sottoclasse ( ( SavingsAccount SavingsAccount ) )

SavingsAccount collegeFund = new SavingsAccount(10);

SavingsAccount collegeFund = new SavingsAccount(10);

// Savings account con interesse del 10%

// Savings account con interesse del 10%

collegeFund.deposit(500);

collegeFund.deposit(500);

// OK uso di un metodo BankAccount con oggetti SavingsAccount // OK uso di un metodo BankAccount con oggetti SavingsAccount

(5)

5 5

Introduzione all'Ereditarietà Introduzione all'Ereditarietà

 Estendere una classe ≠ implementare un'interfaccia: Estendere una classe ≠ implementare un'interfaccia:

la sottoclasse eredita la sottoclasse eredita

sia sia il comportamento il comportamento sia sia lo stato lo stato

 Un vantaggio dell'ereditarietà è il riuso di codice Un vantaggio dell'ereditarietà è il riuso di codice

(6)

6 6

Diagramma di Ereditarietà Diagramma di Ereditarietà

 Ogni classe estende Ogni classe estende

direttamente o indirettamente direttamente o indirettamente

la classe

la classe Object Object

Figure 1:

An Inheritance Diagram

(7)

7 7

Introduzione all'Ereditarietà Introduzione all'Ereditarietà

 Nella sottoclasse, si specificano i campi e i metodi Nella sottoclasse, si specificano i campi e i metodi aggiunti e quelli modificati o sovrascritti

aggiunti e quelli modificati o sovrascritti

public class SavingsAccount extends BankAccount public class SavingsAccount extends BankAccount { {

public SavingsAccount(double rate) public SavingsAccount(double rate) {

{

interestRate = rate;

interestRate = rate;

} }

public void addInterest() public void addInterest() {

{

double interest = getBalance() * interestRate / 100;

double interest = getBalance() * interestRate / 100;

deposit(interest);

deposit(interest);

} }

private double interestRate;

private double interestRate;

} }

(8)

8 8

Introduzione all'Ereditarietà Introduzione all'Ereditarietà

Incapsulamento Incapsulamento : : addInterest addInterest chiama chiama getBalance

getBalance piuttosto che aggiornare il campo piuttosto che aggiornare il campo balance

balance della superclasse (campo privato) della superclasse (campo privato)

 Notare che Notare che addInterest addInterest chiama chiama getBalance

getBalance senza specificare un parametro senza specificare un parametro

implicito (chiamate applicate allo stesso oggetto)

implicito (chiamate applicate allo stesso oggetto)

(9)

9 9

Struttura di un Oggetto Struttura di un Oggetto

di una Sottoclasse di una Sottoclasse

 L'oggetto L'oggetto SavingsAccount SavingsAccount eredita il campo eredita il campo balance

balance da da BankAccount BankAccount , e guadagna un , e guadagna un campo addizionale:

campo addizionale: interestRate interestRate : :

Figure 2:

Layout of a Subclass Object

(10)

10 10

Sintassi 13.1: Ereditarietà Sintassi 13.1: Ereditarietà

class

class SubclassNameSubclassName extendsextends SuperclassNameSuperclassName {{

      methods methods

   instance fields    instance fields }}

 Esempio: Esempio:

  public class SavingsAccount extends BankAccount public class SavingsAccount extends BankAccount { {

public SavingsAccount(double rate) public SavingsAccount(double rate) { {

interestRate = rate; interestRate = rate;

} }

public void addInterest() public void addInterest() { {

double interest = getBalance() * interestRate / 100; double interest = getBalance() * interestRate / 100;

deposit(interest); deposit(interest);

} }

private double interestRate; private double interestRate;

(11)

11 11

Sintassi 13.1: Ereditarietà Sintassi 13.1: Ereditarietà

Scopo Scopo : :

definire una nuova classe che eredita da una classe definire una nuova classe che eredita da una classe

esistente e esistente e

definire i metodi e i campi da aggiungere alla nuova definire i metodi e i campi da aggiungere alla nuova

classe

classe

(12)

12 12

Gerarchie d'Ereditarietà Gerarchie d'Ereditarietà

 Insiemi di classi possono costituire complesse Insiemi di classi possono costituire complesse gerarchie di ereditarietà

gerarchie di ereditarietà

 Esempio Esempio : :

(13)

13 13

Esempio di Gerarchia di Esempio di Gerarchia di Ereditarietà: la Gerarchia

Ereditarietà: la Gerarchia Swing Swing

Figure 4:

A Part of the Hierarchy of Swing User

Interface Components

(14)

14 14

Esempio di Gerarchia di Esempio di Gerarchia di Ereditarietà: la Gerarchia

Ereditarietà: la Gerarchia Swing Swing

 La superclasse La superclasse JComponent JComponent ha ha i metodi i metodi getWidth

getWidth , , getHeight getHeight

 La classe La classe AbstractButton AbstractButton ha i metodi per ha i metodi per settare/leggere testo e icona del bottone

settare/leggere testo e icona del bottone

(15)

15 15

Una Gerarchia più Semplice:

Una Gerarchia più Semplice:

la Gerarchia dei Conti Correnti la Gerarchia dei Conti Correnti

 Si consideri una banca che offra ai suoi clienti i Si consideri una banca che offra ai suoi clienti i seguenti tipi di conto:

seguenti tipi di conto:

Conto Assegni ( Conto Assegni ( checkingAccount checkingAccount ): ):

nessun interesse; nessun interesse;

limitato numero di operazioni gratuite al mese, limitato numero di operazioni gratuite al mese,

operazioni supplementari dietro pagamento di un piccola operazioni supplementari dietro pagamento di un piccola commissione

commissione

Conto Risparmio (savingsAccount Conto Risparmio ( savingsAccount ): ):

Acquista interessi calcolati su base mensile Acquista interessi calcolati su base mensile

(16)

16 16

Una Gerarchia più Semplice:

Una Gerarchia più Semplice:

la Gerarchia dei Conti Correnti la Gerarchia dei Conti Correnti

Figure 5:

 Gerarchia Gerarchia

d'ereditarietà

d'ereditarietà

(17)

17 17

Una Gerarchia più Semplice:

Una Gerarchia più Semplice:

la Gerarchia dei Conti Correnti la Gerarchia dei Conti Correnti

 Tutti i conti supportano il metodo Tutti i conti supportano il metodo getBalance getBalance

 Tutti i conti supportano i metodi Tutti i conti supportano i metodi deposit deposit e e withdraw

withdraw ma le implementazioni differiscono ma le implementazioni differiscono

Il conto assegni necessita di un metodo deductFees Il conto assegni necessita di un metodo deductFees ; ;

Il conto risparmio necessita di un metodo Il conto risparmio necessita di un metodo addInterest

addInterest

(18)

18 18

Ereditare Metodi Ereditare Metodi

1) 1) Sovrascrivere ( Sovrascrivere ( override override ) un metodo: ) un metodo:

Fornire una diversa implementazione di un metodo Fornire una diversa implementazione di un metodo esistente nella superclasse

esistente nella superclasse

Esso deve avere la stessa firma ( Esso deve avere la stessa firma ( signature signature ): ):

stesso

stesso numero di parametri e numero di parametri e stesso stesso tipo tipo

Se si applica il metodo ad un oggetto della sottoclasse Se si applica il metodo ad un oggetto della sottoclasse verrà eseguito il metodo sovrascritto (

verrà eseguito il metodo sovrascritto ( overriding overriding ) )

2) 2) Ereditare un metodo: Ereditare un metodo:

Non si fornisce una nuova implementazione di un metodo Non si fornisce una nuova implementazione di un metodo esistente nella superclasse

esistente nella superclasse

Il metodo della superclasse può ancora essere applicato Il metodo della superclasse può ancora essere applicato all'oggetto della sottoclasse

all'oggetto della sottoclasse

(19)

19 19

Ereditare Metodi Ereditare Metodi

3) 3) Aggiungere un metodo: Aggiungere un metodo:

Fornire un nuovo metodo che non esiste nella Fornire un nuovo metodo che non esiste nella superclasse

superclasse

Il nuovo metodo può essere applicato Il nuovo metodo può essere applicato solo solo ad oggetti ad oggetti della sottoclasse

della sottoclasse

(20)

20 20

Ereditare Campi d'Istanza Ereditare Campi d'Istanza

Non Non si possono sovrascrivere i campi si possono sovrascrivere i campi

 Ereditare un campo: Ereditare un campo:

tutti i campi della superclasse sono automaticamente tutti i campi della superclasse sono automaticamente

ereditati ereditati

 Aggiungere un campo: Aggiungere un campo:

fornire un nuovo campo che non esiste nella fornire un nuovo campo che non esiste nella

superclasse

superclasse

(21)

21 21

Ereditare Campi d'Istanza Ereditare Campi d'Istanza

 Che succede se si definisce un Che succede se si definisce un nuovo nuovo campo con campo con lo lo stesso stesso nome d'un campo della superclasse? nome d'un campo della superclasse?

Ogni oggetto avrebbe due campi d'istanza con lo stesso Ogni oggetto avrebbe due campi d'istanza con lo stesso nome nome

I campi potrebbero avere diversi valori I campi potrebbero avere diversi valori

Lecito ma largamente indesiderabile Lecito ma largamente indesiderabile

(22)

22 22

Implementare la Classe Implementare la Classe

CheckingAccount CheckingAccount

 Sovrascrive Sovrascrive deposit deposit e e withdraw withdraw per poter per poter incrementare il contatore del numero di operazioni incrementare il contatore del numero di operazioni ( ( transazioni transazioni ) effettuate: ) effettuate:

public class CheckingAccount extends BankAccount public class CheckingAccount extends BankAccount { {

public void deposit(double amount) {. . .}

public void deposit(double amount) {. . .}

public void withdraw(double amount) {. . .}

public void withdraw(double amount) {. . .}

public void deductFees() {. . .}

public void deductFees() {. . .} // nuovo metodo // nuovo metodo private int transactionCount;

private int transactionCount; // nuovo campo// nuovo campo } }

(23)

23 23

Implementare la Classe Implementare la Classe

CheckingAccount CheckingAccount

 Ogni oggetto Ogni oggetto CheckingAccount CheckingAccount ha due campi d'istanza:

ha due campi d'istanza:

balance balance

ereditato da BankAccount ereditato da BankAccount

transactionCount transactionCount

nuovo per CheckingAccount nuovo per CheckingAccount

(24)

24 24

Implementare la Classe Implementare la Classe

CheckingAccount CheckingAccount

 Si possono applicare quattro metodi agli oggetti della Si possono applicare quattro metodi agli oggetti della classe

classe CheckingAccount CheckingAccount : :

getBalance() getBalance()

Ereditato da BankAccount Ereditato da BankAccount

deposit(double amount) deposit(double amount)

Sovrascrive il metodo di BankAccount Sovrascrive il metodo di BankAccount

withdraw(double amount) withdraw(double amount)

Sovrascrive il metodo di BankAccount Sovrascrive il metodo di BankAccount

deductFees() deductFees()

Nuovo per CheckingAccount Nuovo per CheckingAccount

(25)

25 25

I Campi Ereditati Sono Privati I Campi Ereditati Sono Privati

 Si consideri il metodo Si consideri il metodo deposit deposit delle classe delle classe CheckingAccount

CheckingAccount

 Non si può semplicemente Non si può semplicemente aggiungere

aggiungere amount amount a a balance balance

 balance balance è campo un è campo un privato privato della superclasse della superclasse

public void deposit(double amount) public void deposit(double amount) { {

transactionCount++;

transactionCount++;

// aggiunge amount a balance // aggiunge amount a balance . . .

. . . }}

(26)

26 26

I Campi Ereditati Sono Privati I Campi Ereditati Sono Privati

 Una sottoclasse Una sottoclasse non non ha accesso ai campi privati ha accesso ai campi privati della sua superclasse

della sua superclasse

 La sottoclasse La sottoclasse deve deve usar l'interfaccia pubblica usar l'interfaccia pubblica

(27)

27 27

Invocare un Metodo Invocare un Metodo

della Superclasse della Superclasse

 Non si può semplicemente chiamare Non si può semplicemente chiamare deposit(amount)

deposit(amount) nel metodo

nel metodo deposit deposit di di CheckingAccount CheckingAccount

 Sarebbe lo stesso di: Sarebbe lo stesso di:

this.deposit(amount) this.deposit(amount)

 Chiamerebbe lo stesso metodo (ricorsione infinita) Chiamerebbe lo stesso metodo (ricorsione infinita)

 Invece, si invoca il metodo della superclasse: Invece, si invoca il metodo della superclasse:

super.deposit(amount)

super.deposit(amount)

(28)

28 28

Invocare un Metodo Invocare un Metodo

della Superclasse della Superclasse

 Adesso si chiama il metodo Adesso si chiama il metodo deposit deposit della classe

della classe BankAccount BankAccount

 Metodo completo: Metodo completo:

public void deposit(double amount) public void deposit(double amount) { {

transactionCount++;

transactionCount++;

// sommare amount a balance: super.deposit(amount); // sommare amount a balance: super.deposit(amount);

} }

(29)

29 29

Sintassi 13.2: Chiamare un Sintassi 13.2: Chiamare un

Metodo di Superclasse Metodo di Superclasse

super.

super.methodNamemethodName((parametersparameters))

 Esempio: Esempio:

public void deposit(double amount) public void deposit(double amount) {{

   transactionCount++;

   transactionCount++;

   super.deposit(amount);

   super.deposit(amount);

}}

Scopo Scopo : chiamare un metodo della superclasse : chiamare un metodo della superclasse invece di quello della classe corrente

invece di quello della classe corrente

(30)

30 30

Implementare i Restanti Metodi Implementare i Restanti Metodi

public class CheckingAccount extends BankAccount public class CheckingAccount extends BankAccount { {

. . . . . .

public void withdraw(double amount) public void withdraw(double amount) {

{

transactionCount++;

transactionCount++;

// sottrae amount da balance // sottrae amount da balance super.withdraw(amount);

super.withdraw(amount);

} }

(31)

31 31

Implementare i Restanti Metodi Implementare i Restanti Metodi

public void deductFees() public void deductFees() {

{

if (transactionCount > FREE_TRANSACTIONS) if (transactionCount > FREE_TRANSACTIONS) {

{

double fees = TRANSACTION_FEE double fees = TRANSACTION_FEE

* (transactionCount - FREE_TRANSACTIONS);

* (transactionCount - FREE_TRANSACTIONS);

super.withdraw(fees);

super.withdraw(fees);

} }

transactionCount = 0;

transactionCount = 0;

} }

. . . . . .

private static final int FREE_TRANSACTIONS = 3;

private static final int FREE_TRANSACTIONS = 3;

private static final double TRANSACTION_FEE = 2.0;

private static final double TRANSACTION_FEE = 2.0;

}}

(32)

32 32

Errore Comune:

Errore Comune:

Oscurare Campi d'Istanza Oscurare Campi d'Istanza

 Una sottoclasse non ha accesso ai campi privati Una sottoclasse non ha accesso ai campi privati della superclasse

della superclasse

 Errore da principianti: "risolvere" il problema Errore da principianti: "risolvere" il problema

aggiungendo un altro campo con lo stesso nome:

aggiungendo un altro campo con lo stesso nome:

public class CheckingAccount extends BankAccount public class CheckingAccount extends BankAccount { {

public void deposit(double amount) public void deposit(double amount)

{ {

transactionCount++;

transactionCount++;

balance = balance + amount;

balance = balance + amount;

} }

. . . . . .

private double balance; private double balance; // da NON fare// da NON fare } }

(33)

33 33

Errore Comune:

Errore Comune:

Oscurare Campi d'Istanza Oscurare Campi d'Istanza

 Adesso il metodo Adesso il metodo deposit deposit viene compilato senza viene compilato senza errori, ma aggiorna il campo

errori, ma aggiorna il campo balance balance sbagliato ! sbagliato !

Figure 6:

Shadowing Instance Fields

(34)

34 34

Costruzione di Sottoclassi Costruzione di Sottoclassi

 super super seguito dalle parentesi seguito dalle parentesi

indica una chiamata al costruttore della superclasse indica una chiamata al costruttore della superclasse

public class CheckingAccount extends BankAccount public class CheckingAccount extends BankAccount { {

public CheckingAccount(double initialBalance) public CheckingAccount(double initialBalance) {

{

// Costruisce la superclasse // Costruisce la superclasse super(initialBalance);

super(initialBalance);

// Inizializza il contatore // Inizializza il contatore transactionCount = 0;

transactionCount = 0;

} }

. . . . . . } }

(35)

35 35

Costruzione di Sottoclassi Costruzione di Sottoclassi

Deve Deve essere essere la prima la prima istruzione nel costruttore istruzione nel costruttore della sottoclasse

della sottoclasse

 Se il costruttore della sottoclasse non chiama quello Se il costruttore della sottoclasse non chiama quello della superclasse, si usa il costruttore di default

della superclasse, si usa il costruttore di default della superclasse

della superclasse

Costruttore di Default: costruttore senza parametri Costruttore di Default: costruttore senza parametri

Se tutti i costruttori della superclasse richiedono Se tutti i costruttori della superclasse richiedono

parametri, allora il compilatore registra un errore

parametri, allora il compilatore registra un errore

(36)

36 36

Sintassi 13.1: Chiamare il Sintassi 13.1: Chiamare il Costruttore della Superclasse Costruttore della Superclasse

className

className((parameters)parameters) {{

   super(

   super(parameters);parameters);

   . . .    . . . }}

Esempio Esempio : :

public CheckingAccount(double initialBalance) public CheckingAccount(double initialBalance) { {

super(initialBalance);

super(initialBalance);

transactionCount = 0;

transactionCount = 0;

}}

Scopo Scopo : Invocare un costruttore della superclasse : Invocare un costruttore della superclasse Si noti che questa istruzione deve essere la prima Si noti che questa istruzione deve essere la prima

nel costruttore della sottoclasse.

nel costruttore della sottoclasse.

(37)

37 37

Conversioni tra Tipi Conversioni tra Tipi Sottoclasse e Superclasse Sottoclasse e Superclasse

 È lecito convertire È lecito convertire

i riferimenti a sottoclassi i riferimenti a sottoclassi

in riferimenti a superclassi in riferimenti a superclassi

SavingsAccount collegeFund = new SavingsAccount(10);

SavingsAccount collegeFund = new SavingsAccount(10);

BankAccount anAccount = collegeFund;

BankAccount anAccount = collegeFund;

Object anObject = collegeFund;

Object anObject = collegeFund;

(38)

38 38

Conversioni tra Tipi Conversioni tra Tipi Sottoclasse e Superclasse Sottoclasse e Superclasse

 I tre riferimenti ad oggetti in I tre riferimenti ad oggetti in collegeFund collegeFund , , anAccount

anAccount , e , e anObject anObject si riferiscono tutti allo si riferiscono tutti allo stesso oggetto di tipo

stesso oggetto di tipo SavingsAccount SavingsAccount

Figure 7:

Variables of Different Types

(39)

39 39

Conversioni tra Tipi Conversioni tra Tipi Sottoclasse e Superclasse Sottoclasse e Superclasse

 I riferimenti a superclasse non sanno tutta la storia I riferimenti a superclasse non sanno tutta la storia dell'oggetto:

dell'oggetto:

 Quando si converte un oggetto d'una sottoclasse in Quando si converte un oggetto d'una sottoclasse in uno del tipo della superclasse:

uno del tipo della superclasse:

Il valore del riferimento rimane lo stesso–è la locazione di Il valore del riferimento rimane lo stesso–è la locazione di memoria dell'oggetto

memoria dell'oggetto

Tuttavia, si dispone di minore informazione circa l'oggetto Tuttavia, si dispone di minore informazione circa l'oggetto

anAccount.deposit(1000);

anAccount.deposit(1000); // OK // OK anAccount.addInterest();

anAccount.addInterest();

// No—non è un metodo della classe cui appartiene anAccount // No—non è un metodo della classe cui appartiene anAccount

(40)

40 40

Conversioni tra Tipi Conversioni tra Tipi Sottoclasse e Superclasse Sottoclasse e Superclasse

 Perché si dovrebbe essere disposti a conoscere Perché si dovrebbe essere disposti a conoscere meno circa un oggetto ?

meno circa un oggetto ?

Riusare codice che sa della superclasse ma non della Riusare codice che sa della superclasse ma non della sottoclasse:

sottoclasse:

 Può essere usato per trasferire denaro da ogni tipo Può essere usato per trasferire denaro da ogni tipo di di BankAccount BankAccount

public void transfer(double amount, BankAccount other) public void transfer(double amount, BankAccount other) { {

withdraw(amount);

withdraw(amount);

other.deposit(amount);

other.deposit(amount);

}}

(41)

41 41

Conversioni tra Tipi Conversioni tra Tipi Sottoclasse e Superclasse Sottoclasse e Superclasse

 Occasionalmente si necessita di convertire Occasionalmente si necessita di convertire un riferimento a superclasse

un riferimento a superclasse in un riferimento a sottoclasse in un riferimento a sottoclasse

 Questo Questo cast cast è è pericoloso pericoloso : :

se ci si sbaglia viene lanciata un eccezione se ci si sbaglia viene lanciata un eccezione

BankAccount anAccount = (BankAccount) anObject;

BankAccount anAccount = (BankAccount) anObject;

(42)

42 42

Conversioni tra Tipi Conversioni tra Tipi Sottoclasse e Superclasse Sottoclasse e Superclasse

 Soluzione: usare l'operatore Soluzione: usare l'operatore instanceof instanceof

 instanceof instanceof : :

controlla se un oggetto appartenga o meno controlla se un oggetto appartenga o meno

ad un particolare tipo ad un particolare tipo

if (anObject instanceof BankAccount) if (anObject instanceof BankAccount) { {

BankAccount anAccount = (BankAccount) anObject;

BankAccount anAccount = (BankAccount) anObject;

. . . . . . } }

(43)

43 43

Sintassi 13.4:

Sintassi 13.4:

L'Operatore

L'Operatore Instanceof Instanceof

object

object instanceofinstanceof TypeNameTypeName

Esempio Esempio : :

if (anObject instanceof BankAccount) if (anObject instanceof BankAccount) { {

BankAccount anAccount = (BankAccount) anObject;

BankAccount anAccount = (BankAccount) anObject;

. . . . . . }}

Scopo Scopo : : (operatore booleano) (operatore booleano) restituisce

restituisce true true se l'oggetto è un'istanza di se l'oggetto è un'istanza di TypeName

TypeName (o uno di suoi sottotipi), (o uno di suoi sottotipi),

e e false false altrimenti altrimenti

(44)

44 44

Polimorfismo Polimorfismo

 In Java, il tipo di una variabile non determina In Java, il tipo di una variabile non determina completamente il tipo d'oggetto al quale essa si completamente il tipo d'oggetto al quale essa si

riferisce riferisce

 Le chiamate dei metodi sono determinate dal tipo Le chiamate dei metodi sono determinate dal tipo effettivo dell'oggetto e non dal tipo di riferimento effettivo dell'oggetto e non dal tipo di riferimento

BankAccount aBankAccount = new SavingsAccount(1000);

BankAccount aBankAccount = new SavingsAccount(1000);

// aBankAccount mantiene un riferimento a un SavingsAccount // aBankAccount mantiene un riferimento a un SavingsAccount

BankAccount anAccount = new CheckingAccount();

BankAccount anAccount = new CheckingAccount();

anAccount.deposit(1000);

anAccount.deposit(1000);

// chiama "deposit" di CheckingAccount // chiama "deposit" di CheckingAccount

(45)

45 45

Polimorfismo Polimorfismo

 Il compilatore necessita di controllare che si Il compilatore necessita di controllare che si invochino solo metodi leciti

invochino solo metodi leciti

Object anObject = new BankAccount();

Object anObject = new BankAccount();

anObject.deposit(1000);

anObject.deposit(1000); // sbagliato ! // sbagliato !

(46)

46 46

Polimorfismo Polimorfismo

Polimorfismo Polimorfismo : abilità di riferirsi ad oggetti di tipi : abilità di riferirsi ad oggetti di tipi differenti dal comportamento variabile

differenti dal comportamento variabile

 Polimorfismo all'opera: Polimorfismo all'opera:

A seconda dei tipi di amount ed altro, A seconda dei tipi di amount ed altro, saranno chiamate diverse versioni di

saranno chiamate diverse versioni di withdraw withdraw e e deposit

deposit

public void transfer(double amount, BankAccount other) public void transfer(double amount, BankAccount other) { {

withdraw(amount);

withdraw(amount); // abbreviazione di this.withdraw(amount)// abbreviazione di this.withdraw(amount) other.deposit(amount);

other.deposit(amount);

}}

(47)

47 47

AccountTester.java AccountTester.java

01: /**

01: /**

02: Programma per testare la classe BankAccount 02: Programma per testare la classe BankAccount 03: e le sue sottoclassi.

03: e le sue sottoclassi.

04: */

04: */

05: public class AccountTester 05: public class AccountTester 06: {

06: {

07: public static void main(String[] args) 07: public static void main(String[] args) 08: {

08: {

09: SavingsAccount momsSavings 09: SavingsAccount momsSavings

10: = new SavingsAccount(0.5);

10: = new SavingsAccount(0.5);

11:

11:

12: CheckingAccount harrysChecking 12: CheckingAccount harrysChecking 13: = new CheckingAccount(100);

13: = new CheckingAccount(100);

14:

14:

15: momsSavings.deposit(10000);

15: momsSavings.deposit(10000);

16: 16:

(48)

48 48

AccountTester.java AccountTester.java

17: momsSavings.transfer(2000, harrysChecking);

17: momsSavings.transfer(2000, harrysChecking);

18: harrysChecking.withdraw(1500);

18: harrysChecking.withdraw(1500);

19: harrysChecking.withdraw(80);

19: harrysChecking.withdraw(80);

20: 20:

21: momsSavings.transfer(1000, harrysChecking);

21: momsSavings.transfer(1000, harrysChecking);

22: harrysChecking.withdraw(400);

22: harrysChecking.withdraw(400);

23: 23:

24: // Simulate end of month 24: // Simulate end of month 25: momsSavings.addInterest();

25: momsSavings.addInterest();

26: harrysChecking.deductFees();

26: harrysChecking.deductFees();

27:

27:

28: System.out.println("Mom's savings balance = $“

28: System.out.println("Mom's savings balance = $“

29: + momsSavings.getBalance());

29: + momsSavings.getBalance());

30: 30:

31: System.out.println("Harry's checking balance = $“

31: System.out.println("Harry's checking balance = $“

32: + harrysChecking.getBalance());

32: + harrysChecking.getBalance());

33: } 33: } 34: } 34: }

(49)

49 49

BankAccount.java BankAccount.java

01: /**

01: /**

02: Un conto ha un balance modificabile con 02: Un conto ha un balance modificabile con 03: depositi e prelievi.

03: depositi e prelievi.

04: */

04: */

05: public class BankAccount 05: public class BankAccount 06: {

06: { 07: /**

07: /**

08: Costruisce un conto con saldo zero.

08: Costruisce un conto con saldo zero.

09: */

09: */

10: public BankAccount() 10: public BankAccount() 11: {

11: {

12: balance = 0;

12: balance = 0;

13: } 13: } 14: 14:

15: /**

15: /**

16: Costruisce un conto con un dato saldo.

16: Costruisce un conto con un dato saldo.

17: @param initialBalance saldo iniziale 17: @param initialBalance saldo iniziale 18: */

18: */

(50)

50 50

BankAccount.java BankAccount.java

19: public BankAccount(double initialBalance) 19: public BankAccount(double initialBalance) 20: {

20: {

21: balance = initialBalance;

21: balance = initialBalance;

22: } 22: } 23:

23:

24: /**

24: /**

25: Deposita denaro sul conto.

25: Deposita denaro sul conto.

26: @param amount l'ammontare da depositare 26: @param amount l'ammontare da depositare 27: */

27: */

28: public void deposit(double amount) 28: public void deposit(double amount) 29: {

29: {

30: balance = balance + amount;

30: balance = balance + amount;

31: } 31: } 32: 32:

33: /**

33: /**

34: ritira denaro dal conto.

34: ritira denaro dal conto.

35: @param amount l'ammontare da ritirare 35: @param amount l'ammontare da ritirare 36: */

36: */

(51)

51 51

BankAccount.java BankAccount.java

37: public void withdraw(double amount) 37: public void withdraw(double amount) 38: {

38: {

39: balance = balance - amount;

39: balance = balance - amount;

40: } 40: } 41: 41:

42: /**

42: /**

43: Ottiene il saldo corrente dal conto.

43: Ottiene il saldo corrente dal conto.

44: @return il saldo corrente 44: @return il saldo corrente 45: */

45: */

46: public double getBalance() 46: public double getBalance() 47: {

47: {

48: return balance;

48: return balance;

49: } 49: } 50:

50:

51: /**

51: /**

52: Trasferisce denaro dal conto ad altro conto 52: Trasferisce denaro dal conto ad altro conto 53: @param amount l'ammondtare del trasferimento 53: @param amount l'ammondtare del trasferimento 54: @param other l'altro conto

54: @param other l'altro conto 55: */

55: */

(52)

52 52

BankAccount.java BankAccount.java

56: public void transfer(double amount, BankAccount other) 56: public void transfer(double amount, BankAccount other) 57: {

57: {

58: withdraw(amount);

58: withdraw(amount);

59: other.deposit(amount);

59: other.deposit(amount);

60: } 60: } 61: 61:

62: private double balance;

62: private double balance;

63: } 63: }

(53)

53 53

CheckingAccount.java CheckingAccount.java

01: /**

01: /**

02: Un conto assegni che carica commissioni su operazioni.

02: Un conto assegni che carica commissioni su operazioni.

03: */

03: */

04: public class CheckingAccount extends BankAccount 04: public class CheckingAccount extends BankAccount 05: {

05: {

06: /**

06: /**

07: Costruisce un conto assegni con il dato saldo.

07: Costruisce un conto assegni con il dato saldo.

08: @param initialBalance saldo iniziale 08: @param initialBalance saldo iniziale 09: */

09: */

10: public CheckingAccount(double initialBalance) 10: public CheckingAccount(double initialBalance) 11: {

11: {

12: // Costruisce la superclasse 12: // Costruisce la superclasse 13: super(initialBalance);

13: super(initialBalance);

14:

14:

15: // Inizializza il contatore operazioni 15: // Inizializza il contatore operazioni 16: transactionCount = 0;

16: transactionCount = 0;

17: } 17: } 18: 18:

(54)

54 54

CheckingAccount.java CheckingAccount.java

19: public void deposit(double amount) 19: public void deposit(double amount) 20: {

20: {

21: transactionCount++;

21: transactionCount++;

22: // aggiunge amount a balance 22: // aggiunge amount a balance 23: super.deposit(amount);

23: super.deposit(amount);

24: } 24: } 25:

25:

26: public void withdraw(double amount) 26: public void withdraw(double amount) 27: {

27: {

28: transactionCount++;

28: transactionCount++;

29: // sottrae amount da balance 29: // sottrae amount da balance 30: super.withdraw(amount);

30: super.withdraw(amount);

31: } 31: } 32: 32:

33: /**

33: /**

34: deduce le commissioni accumulate e ripristina il 34: deduce le commissioni accumulate e ripristina il 35: contatore delle operazioni.

35: contatore delle operazioni.

36: */

36: */

(55)

55 55

CheckingAccount.java CheckingAccount.java

37: public void deductFees() 37: public void deductFees() 38: {

38: {

39: if (transactionCount > FREE_TRANSACTIONS) 39: if (transactionCount > FREE_TRANSACTIONS) 40: {

40: {

41: double fees = TRANSACTION_FEE * 41: double fees = TRANSACTION_FEE *

42: (transactionCount - FREE_TRANSACTIONS);

42: (transactionCount - FREE_TRANSACTIONS);

43: super.withdraw(fees);

43: super.withdraw(fees);

44: } 44: }

45: transactionCount = 0;

45: transactionCount = 0;

46: } 46: } 47: 47:

48: private int transactionCount;

48: private int transactionCount;

49: 49:

50: private static final int FREE_TRANSACTIONS = 3;

50: private static final int FREE_TRANSACTIONS = 3;

51: private static final double TRANSACTION_FEE = 2.0;

51: private static final double TRANSACTION_FEE = 2.0;

52: } 52: }

(56)

56 56

SavingsAccount.java SavingsAccount.java

01: /**

01: /**

02: Un conto che guadagna interessi ad un tasso fissato.

02: Un conto che guadagna interessi ad un tasso fissato.

03: */

03: */

04: public class SavingsAccount extends BankAccount 04: public class SavingsAccount extends BankAccount 05: {

05: { 06: /**

06: /**

07: Costruisce un conto con un dato tasso d'interesse.

07: Costruisce un conto con un dato tasso d'interesse.

08: @param rate il tasso d'interesse 08: @param rate il tasso d'interesse 09: */

09: */

10: public SavingsAccount(double rate) 10: public SavingsAccount(double rate) 11: {

11: {

12: interestRate = rate;

12: interestRate = rate;

13: } 13: } 14:14:

(57)

57 57

SavingsAccount.java SavingsAccount.java

15: /**

15: /**

16: Aggiunge gli interessi maturati al saldo del conto.

16: Aggiunge gli interessi maturati al saldo del conto.

17: */

17: */

18: public void addInterest() 18: public void addInterest() 19: {

19: {

20: double interest = getBalance() * interestRate / 100;

20: double interest = getBalance() * interestRate / 100;

21: deposit(interest);

21: deposit(interest);

22: } 22: } 23: 23:

24: private double interestRate;

24: private double interestRate;

25: } 25: }

(58)

58 58

 Output Output

SavingsAccount.java SavingsAccount.java

Mom's savings balance = $7035.0 Mom's savings balance = $7035.0 Harry's checking balance = $1116.0 Harry's checking balance = $1116.0

(59)

59 59

Controllo d'Accesso Controllo d'Accesso

 Java ha quattro livelli di controllo d'accesso ai campi, Java ha quattro livelli di controllo d'accesso ai campi, metodi e classe:

metodi e classe:

Accesso Pubblico ( Accesso Pubblico ( public public ) )

Si può accedere da metodi di tutte le classi Si può accedere da metodi di tutte le classi

Accesso Privato ( Accesso Privato ( private private ) )

Si può accedere da metodi della loro prorpa classe Si può accedere da metodi della loro prorpa classe

Accesso Protetto ( Accesso Protetto ( protected protected ) )

Cfr. Argomenti avanzati 12.3 Cfr. Argomenti avanzati 12.3

Accesso di Pacchetto (package Accesso di Pacchetto ( package ) )

Default, quando non si specifica un altro accesso Default, quando non si specifica un altro accesso

Si può accedere da tutte le classi nello stesso package Si può accedere da tutte le classi nello stesso package

Va bene per classi default, non altrettanto per i campi d'istanza Va bene per classi default, non altrettanto per i campi d'istanza

(60)

60 60

Livelli d'Accesso Raccomandati Livelli d'Accesso Raccomandati

 Campi d'istanza e statici: sempre Campi d'istanza e statici: sempre private private . . Tranne:

Tranne:

Le costanti Le costanti public static final public static final sono utili e sono utili e sicure

sicure

Alcuni oggetti, come System.out Alcuni oggetti, come System.out , hanno bisogno di , hanno bisogno di essere accessibili a tutti i programmi (

essere accessibili a tutti i programmi ( public public ) )

A volte, le classi di un pacchetto devono collaborare molto A volte, le classi di un pacchetto devono collaborare molto strettamente (si dà ad alcuni campi l'accesso di

strettamente (si dà ad alcuni campi l'accesso di pacchetto); meglio le classi interne

pacchetto); meglio le classi interne

(61)

61 61

Livelli d'Accesso Raccomandati Livelli d'Accesso Raccomandati

 Metodi: Metodi: public public o o private private

 Classi ed Interfacce: Classi ed Interfacce: public public o pacchetto o pacchetto

Alternativa migliore all'accesso di pacchetto: classi interne Alternativa migliore all'accesso di pacchetto: classi interne

In generale, le classi interne non dovrebbero essere pubbliche In generale, le classi interne non dovrebbero essere pubbliche (ci sono alcune eccezioni, es.,

(ci sono alcune eccezioni, es., Ellipse2D.Double Ellipse2D.Double ) )

 Attenzione all'accesso di pacchetto involontario Attenzione all'accesso di pacchetto involontario (dimenticando di specificare

(dimenticando di specificare public

public o o private private ) )

(62)

62 62

Object Object : : la Superclasse Universale la Superclasse Universale

 Ogni classe definita senza una clausola Ogni classe definita senza una clausola extends extends esplicita estende automaticamente

esplicita estende automaticamente Object Object

Figure 8:

(63)

63 63

Object Object : : la Superclasse Universale la Superclasse Universale

 Metodi più utili: Metodi più utili:

String toString() String toString()

boolean equals(Object otherObject) boolean equals(Object otherObject)

Object clone() Object clone()

 È una buona idea quella di sovrascrivere questi È una buona idea quella di sovrascrivere questi metodi nelle proprie classi

metodi nelle proprie classi

(64)

64 64

Sovrascrivere il Metodo Sovrascrivere il Metodo

tostring() tostring()

 Restituisce una rappresentazione in forma di stringa Restituisce una rappresentazione in forma di stringa dell'oggetto

dell'oggetto

 Utile per il debugging: Utile per il debugging:

Rectangle box = new Rectangle(5, 10, 20, 30);

Rectangle box = new Rectangle(5, 10, 20, 30);

String s = box.toString();

String s = box.toString();

// setta s a "java.awt.Rectangle[x=5,y=10,width=20,height=30]"

// setta s a "java.awt.Rectangle[x=5,y=10,width=20,height=30]"

(65)

65 65

Sovrascrivere il Metodo Sovrascrivere il Metodo

toString toString

 toString toString viene chiamato ogni qual volta si viene chiamato ogni qual volta si concatena una stringa con un oggetto:

concatena una stringa con un oggetto:

 Object.toString Object.toString stampa il nome della classe stampa il nome della classe e l'hash-code dell'oggetto:

e l'hash-code dell'oggetto:

"box=" + box;

"box=" + box;

// cioè "box=java.awt.Rectangle[x=5,y=10,width=20,height=30]"

// cioè "box=java.awt.Rectangle[x=5,y=10,width=20,height=30]"

BankAccount momsSavings = new BankAccount(5000);

BankAccount momsSavings = new BankAccount(5000);

String s = momsSavings.toString();

String s = momsSavings.toString();

// setta s a qualcosa come "BankAccount@d24606bf"

// setta s a qualcosa come "BankAccount@d24606bf"

(66)

66 66

Sovrascrivere il Metodo Sovrascrivere il Metodo

tostring() tostring()

 Per una rappresentazione più carina di un oggetto si Per una rappresentazione più carina di un oggetto si sovrascriva

sovrascriva toString toString : :

 Questo funziona anche meglio: Questo funziona anche meglio:

public String toString() public String toString() { {

return "BankAccount[balance=" + balance + "]";

return "BankAccount[balance=" + balance + "]";

}}

BankAccount momsSavings = new BankAccount(5000);

BankAccount momsSavings = new BankAccount(5000);

String s = momsSavings.toString();

String s = momsSavings.toString();

// setta s a "BankAccount[balance=5000]"

// setta s a "BankAccount[balance=5000]"

(67)

67 67

Sovrascrivere il Metodo Sovrascrivere il Metodo

equals() equals()

 equals equals testa l'uguaglianza del contenuto testa l'uguaglianza del contenuto

Figure 9:

Two References to Equal Objects

(68)

68 68

Sovrascrivere il Metodo Sovrascrivere il Metodo

equals() equals()

 == == testa per l'uguaglianza della locazione testa per l'uguaglianza della locazione

Figure 10:

Two References to the Same Object

(69)

69 69

Sovrascrivere il Metodo Sovrascrivere il Metodo

equals() equals()

 Definire il metodo Definire il metodo equals equals per testare se due per testare se due oggetti hanno un uguale stato

oggetti hanno un uguale stato

 Nella ridefinizione del metodo Nella ridefinizione del metodo equals equals , non si può , non si può cambiare la firma; si può invece usare il cast:

cambiare la firma; si può invece usare il cast:

public class Coin public class Coin { {

. . . . . .

public boolean equals(Object otherObject) public boolean equals(Object otherObject) {

{

Coin other = (Coin) otherObject;

Coin other = (Coin) otherObject;

return name.equals(other.name) && value == other.value;

return name.equals(other.name) && value == other.value;

} }

. . . . . . }}

(70)

70 70

Sovrascrivere il Metodo Sovrascrivere il Metodo

equals() equals()

 Si può anche sovrascrivere il metodo Si può anche sovrascrivere il metodo hashCode hashCode in modo che oggetti eguali abbiano lo stesso hash- in modo che oggetti eguali abbiano lo stesso hash-

code

code

(71)

71 71

Sovrascrivere il Metodo Sovrascrivere il Metodo

clone() clone()

 Copiare un riferimento ad un oggetto risulta in due Copiare un riferimento ad un oggetto risulta in due riferimenti allo stesso oggetto

riferimenti allo stesso oggetto

BankAccount account2 = account;

BankAccount account2 = account;

(72)

72 72

Sovrascrivere il Metodo Sovrascrivere il Metodo

clone() clone()

Object 11:

Cloning Objects

 A volte serve fare una copia dell'oggetto A volte serve fare una copia dell'oggetto

(73)

73 73

Sovrascrivere il Metodo Sovrascrivere il Metodo

clone() clone()

 Si definisce il metodo Si definisce il metodo clone clone per creare un nuovo per creare un nuovo oggetto (cfr. argomenti avanzati 13.6)

oggetto (cfr. argomenti avanzati 13.6)

 Uso di Uso di clone clone : :

 Si deve fare un cast del valore ritornato perché il tipo Si deve fare un cast del valore ritornato perché il tipo di valore restituito da clone è semplicemente

di valore restituito da clone è semplicemente Object

Object

BankAccount clonedAccount = (BankAccount) account.clone();

BankAccount clonedAccount = (BankAccount) account.clone();

(74)

74 74

Il Metodo

Il Metodo Object.clone Object.clone

 Crea copie profonde ( Crea copie profonde ( shallow shallow ) )

(75)

75 75

Il Metodo

Il Metodo Object.clone Object.clone

Non Non clona sistematicamente tutti gli oggetti contenuti clona sistematicamente tutti gli oggetti contenuti

 Deve essere usato con cautela Deve essere usato con cautela

 È dichiarato come È dichiarato come protected protected ; ; previene chiamate accidentali di

previene chiamate accidentali di x.clone() x.clone() se la se la classe alla quale

classe alla quale x x appartiene non ha ridefinito appartiene non ha ridefinito clone

clone rendendolo pubblico rendendolo pubblico

 Si dovrebbe sovrascrivere il metodo Si dovrebbe sovrascrivere il metodo clone clone in in

maniera accurata (cfr. argomenti avanzati 12.6)

maniera accurata (cfr. argomenti avanzati 12.6)

Riferimenti

Documenti correlati

Dovendo risolvere l’equazione con le condizioni al contorno di Dirichlet utilizzando il metodo a 9 punti schematizzare, a fianco del dominio, la struttura della matrice dei

Il browser, infatti, legge la pagina dall'alto verso il basso, quando incontra il Tag <SCRIPT> continua a leggere sempre nello stesso verso ma interpreta le righe in

Finalmente arrivano informazioni sul complice della Signora Violet, l’abilissima ladra arrestata da Numerik.. Gli indizi sono contenuti in una busta chiusa: l’ispettore Numerik la

Lo Studio ringrazia per l’attenzione riservatagli e rimane a disposizione per ogni ulteriore chiarimento. 662/96, non possono chiedere il rimborso del credito Iva risultante

nell'edificio dopo la costruzione di quest'ultimo per iniziativa di parte dei condomini, non rientra nella proprietà comune di tutti i condomini, ma appartiene in proprietà a quelli

Era infatti considerato un temibile oppositore, simbolo della lotta di liberazione dei neri.. 46 Quale di questi trittici di personaggi visse durante il «secolo

Il sistema operativo, quando c’è bisogno di eseguire un nuovo servizio (e quindi di mandare in esecuzione un nuovo processo) decide di mandarlo in esecuzione sul processore che

E’ sempre possibile rendere positivo il coefficiente quadratico.. Infatti, nel caso in cui a < 0 , basterà moltiplicare per -1