Realizzare classi. Cosa abbiamo fatto finora. Realizzare classi. Realizzare classi. Realizzare classi. Realizzare classi

Documenti analoghi
Programmazione. Cognome... Nome... Matricola... Prova scritta del 22 settembre Negli esercizi proposti si utilizzano le seguenti classi:

Programmazione. Cognome... Nome... Matricola... Prova scritta del 11 luglio 2014

VBA è un linguaggio di scripting derivato da Visual Basic, da cui prende il nome. Come ogni linguaggio ha le sue regole.

Uso di metodi statici. Walter Didimo

Corso di Laurea Ingegneria Informatica Fondamenti di Informatica 1

Variabili. Unità 2. Domenico Daniele Bloisi. Corso di Programmazione e Metodi Numerici Ingegneria Aerospaziale BAER

Definizione di metodi

Esonero del corso di Programmazione a Oggetti

Unità Didattica 3 Linguaggio C. Generalità sulle Funzioni. Variabili locali e globali. Passaggio di parametri per valore.

public BankAccount() { balance = 0; } public BankAccount(double initialbalance) { balance = initialbalance; }

Corso di Laurea Ingegneria Informatica Laboratorio di Informatica

Esercitazione 4. Comandi iterativi for, while, do-while

Livelli di astrazione

4 GLI ARRAY E LE STRINGHE

Classi. Oggetti e classi. Creazione e inizializzazione di oggetti in C++ Distruzione di oggetti in C++

Istruzioni di ripetizione in Java 1

Corso di Fondamenti di Informatica Classi di istruzioni 2

Procedura operativa per la gestione della funzione di formazione classi prime

public double getlato() restituisce la lunghezza del lato del quadrato che esegue il metodo.

Linguaggio C: introduzione

Somma di numeri floating point. Algoritmi di moltiplicazione e divisione per numeri interi

Diagrammi a blocchi 1

PROGRAMMAZIONE STRUTTURATA

Fondamenti di Informatica. Algoritmi di Ricerca e di Ordinamento

Individuazione di sottoproblemi

Un esempio di if annidati

Problema: calcolare il massimo tra K numeri

Informatica/ Ing. Meccanica/ Prof. Verdicchio/ 14/02/2012 / Foglio delle domande / VERSIONE 1

La codifica. dell informazione

AXO - Architettura dei Calcolatori e Sistema Operativo. organizzazione strutturata dei calcolatori

ACCESS. Database: archivio elettronico, dotato di un programma di interfaccia che facilita la registrazione e la ricerca dei dati.

Appunti di informatica. Lezione 4 anno accademico Mario Verdicchio

Lezioni di Ricerca Operativa 2 Dott. F. Carrabs

DESCRIZIONE CREAZIONE APP Si suddivide in 4 fasi di lavoro: 1. PIANIFICAZIONE; 2. PROGETTAZIONE; 3. SVILUPPO; 4. DISTRIBUZIONE.

Codice binario. Codice. Codifica - numeri naturali. Codifica - numeri naturali. Alfabeto binario: costituito da due simboli

Capitolo 3. Realizzare classi. Cay S. Horstmann Concetti di informatica e fondamenti di Java quarta edizione

Gestione delle eccezioni in Java

Istruzioni iterative. Istruzioni iterative

IL CONCETTO DI FILE. È illecito operare oltre la fine del file.

Programmazione Orientata agli Oggetti

VALORIZZAZIONE MOVIMENTI DI SCARICO E VALORIZZAZIONE TRASFERIMENTO COSTI DI ANALITICA

Le Strutture di controllo Del Linguaggio C. Prof. Francesco Accarino IIS Altiero Spinelli Sesto San Giovanni

Introduzione a Visual Basic Lezione 2 Cicli e anomalie

UD4 - MATLAB. M-file. Efficienza degli algoritmi. Formati d uscita

Programmazione Orientata agli Oggetti in Linguaggio Java

1 Definizione di sistema lineare omogeneo.

Ingegneria del Software

Introduzione alle macchine a stati (non definitivo)

Fondamenti VBA. Che cos è VBA

7 Disegni sperimentali ad un solo fattore. Giulio Vidotto Raffaele Cioffi

Fortran in pillole : prima parte

Un convertitore D/A o digitale/analogico è un dispositivo che ha lo scopo di

Istruzioni di ciclo. Unità 4. Corso di Laboratorio di Informatica Ingegneria Clinica BCLR. Domenico Daniele Bloisi

VISUAL BASIC FOR APPLICATION

Laboratorio di Programmazione Lezione 1. Cristian Del Fabbro

Informatica B. Sezione D. Scuola di Ingegneria Industriale Laurea in Ingegneria Energetica Laurea in Ingegneria Meccanica

GUIDA RAPIDA EDILCONNECT

Note_Batch_Application 04/02/2011

Come utilizzare i riferimenti assoluti e relativi in Microsoft Excel

Programmazione ad Oggetti

Esercizio 6 Realizzare una classe astratta per le Figure piane e due sottoclassi, la sottoclasse Quadrato e la sottoclasse Rettangolo.

Programma per la generazione di filastrocche

Introduzione al Linguaggio C ed all IDE DEV-C++

Oggetti e classi. Cos è un oggetto

ESAME DI FONDAMENTI DI INFORMATICA I ESAME DI ELEMENTI DI INFORMATICA. 28 Gennaio 1999 PROVA SCRITTA

INDICE. Vista Libretto Livello Digitale 2. Importazione di dati da strumento 3. Inserisci File Vari 5. Compensazione Quote 5.

Classi ed Oggetti in JAVA

Files in C++ Fondamenti di Informatica. R. Basili. a.a

Manutenzione periodica al PIANO DEI CONTI

Refactoring 5 Sposta Metodo. 5 Sposta Metodo. 5 Sposta Metodo - Codice iniziale

Risoluzione di problemi ingegneristici con Excel

Manuale di Aggiornamento BOLLETTINO. Rel B. DATALOG Soluzioni Integrate a 32 Bit

Cos è un algoritmo. Si dice algoritmo la descrizione di un metodo di soluzione di un problema che sia

Traduzione e adattamento a cura di Gylas per Giochi Rari. Versione 1.1 Novembre

Laboratorio di Architettura lezione 5. Massimo Marchiori W3C/MIT/UNIVE

Laboratorio di Architettura degli Elaboratori

1 DESCRIZIONE DELLE FUNZIONI REGISTRAZIONE UTENZE INTERNET Caricamento utente internet (data entry)... 3

Normalizzazione. Definizione

Equazioni, funzioni e algoritmi: il metodo delle secanti

Array multidimensionali e stringhe

1 IL LINGUAGGIO MATEMATICO

MANUALE ISCRIZIONE E DOMANDA ON-LINE

Mini-Corso di Informatica

Lavoro & Previdenza La circolare su temi previdenziali e giuslavoristici

Word Formattazione del testo. Samuele Mazzolini

Indice. Introduzione Collegamento iniziale Identificazione della sede operativa (sede di lavoro) 5

Le equazioni di I grado

Il concetto di calcolatore e di algoritmo

COME ACCEDERE 5 COME VERSARE IL DENARO 6 COME DISPORRE DEL DENARO 7 LA TUA BANCA ON-LINE 8 SICUREZZA 9 ALTRE INFORMAZIONI UTILI 10

Funzioni condizionali

Oggetto: Utility per la variazione massiva del codice IVA.

PG5 Starter Training Applicazione File System Daniel Ernst EN Stefano Peracchi IT

Guida Compilazione Questionario SCUOLA DELL INFANZIA PARITARIA

L accesso ai dispositivi esterni (tastiera, monitor, file,...) viene gestito mediante canali di comunicazione.

FONDAMENTI DI INFORMATICA Lezione n. 11

Anno 2. Radicali algebrici e aritmetici: condizioni di esistenza

La segreteria didattica dovrà eseguire semplici operazioni per effettuare lo scrutinio:

Pagamento Oneri. Gli oneri di istruttoria ed i bolli vengono pagati all invio della richiesta.

Definizione. Il valore assoluto lascia inalterato ciò che è già positivo e rende positivo ciò che positivo non è.

Rappresentazioni numeriche

Transcript:

Cosa abbiamo fatto finora Abbiamo visto: tipi di dato base (numeri, booleani e caratteri) oggetti e riferimenti a oggetti di un tipo già definito (String e Rectangle) strutture di controllo (sequenza, scelta, iterazione) una struttura di dati (array) Ora vediamo come progettare e realizzare classi. Vogliamo realizzare un nuovo concetto e dobbiamo eseguire un processo di astrazione per individuare e distinguere ciò che è rilevante nel concetto da quelli che sono i dettagli tecnici : quando saliamo su una automobile ci interessa che, girando la chiave si metta in moto e ci disinteressiamo di come ciò avvenga. Il costruttore dell automobile ha realizzato per noi un esemplare di auto che si accende girando la chiave. Questo è il concetto rilevante per chi usa l auto. Il dettaglio tecnico è invece rilevante per l ingegnere meccanico che progetta il motore. Gli oggetti vengono descritti nelle classi; il comportamento degli oggetti è noto usandoli mediante l invocazione di metodi. Possiamo considerare un oggetto come una scatola nera (black box) dotata di: un interfaccia pubblica costituita dai metodi che l utente può usare e che definisce il comportamento dell oggetto; una realizzazione nascosta, costituita dal codice dei metodi e dai dati. Il primo esempio di programma realizzava l invio all output standard di un messaggio di saluto. Il primo esempio di classe realizzerà un concetto per costruire un messaggio di saluto, che potrà poi essere inviato all output standard. La parte rilevante è la costruzione del messaggio. Diamo un nome al nostro nuovo concetto, nuovo tipo di dato, e costruiamo una classe: public class Saluto {... Cosa vogliamo che faccia un metodo che agisce su un oggetto di tipo Saluto? restituire il messaggio Costruiremo un metodo ciao, in modo tale che, se primo è una variabile oggetto di tipo Saluto, invocando il metodo tramite l oggetto primo.ciao() ci venga restituita il messaggio. 1

Un concetto ha una forma (dati, campi) e un comportamento (metodi). La forma del nostro concetto Saluto sarà un messaggio e quindi una variabile di tipo String. Un oggetto di tipo NuovoConcetto, creato con l operatore new, si chiama esemplare o istanza della classe NuovoConcetto. I dati dell oggetto si chiamano: campi o variabili di esemplare, o variabili di istanza. Definizione di una variabile di istanza (campo di esemplare). Sintassi. accesso tipo nomevariabile; Esempio. private String messaggio; accesso: private tipo: String nomevariabile: messaggio Cosa significa private. Significa che solamente i metodi della classe possono accedere a quella variabile. Per conoscere dall esterno informazioni su questa variabile si devono utilizzare dei metodi di accesso (pubblici). Per modificare dall esterno lo stato dell oggetto si devono usare dei metodi di modifica (pubblici). L utente esterno non sa come è stato realizzato l oggetto (dettaglio tecnico) ma lo può usare attraverso i suoi metodi (rilevante). Questa caratteristica si chiama incapsulamento. In tale modo i dati sono protetti ed è chi progetta la classe che definisce e scrive il codice dei metodi con i quali si può accedere a tali dati. I dati si possono definire public (non è un errore di sintassi), ma ciò è contrario alle direttive della programmazione a oggetti. Costruiamo l interfaccia pubblica, che permetterà all utente di manipolare l oggetto. In questo esempio avremo un solo metodo che restituirà il contenuto del messaggio: public String ciao(){ return messaggio; Sintassi. accesso tipodiritorno nomemetodo (parametri){ //corpo del metodo Un metodo di una interfaccia pubblica: 1. ha uno specificatore di accesso public 2. ha un tipo di dato restituito String 3. ha un nome ciao 4. ha un eventuale elenco di parametri ( ) 5. ha un corpo { return messaggio; Cosa fa l istruzione return: interrompe l esecuzione del metodo e restituisce un valore all istruzione che ha invocato il metodo: il controllo ritorna al metodo invocante che riprende l esecuzione (sospesa). 2

Sintassi. return espressione; L espressione definisce il valore restituito dal metodo e deve essere del tipo dichiarato nella intestazione del metodo. Il metodo ciao deve restituire una stringa: messaggio è di tipo String e il tipo restituito dal metodo èstring. Un metodo non restituisce necessariamente un valore: in questo caso il metodo è di tipo void. Al termine di un metodo con valore restituito di tipo void, viene eseguito automaticamente un istruzione return. Il compilatore segnala un errore se si termina un metodo con un valore restituito, diverso da void, senza un enunciato return. Quando un oggetto viene creato, esso viene inizializzato dal costruttore dell oggetto. Costruttore. accesso NomeClasse (tipo argomento, ) { //corpo del costruttore Esempio. public Saluto(){ messaggio = Ciao ; Lo scopo di un costruttore è quello di inizializzare le variabili di esemplare. Come si invoca un costruttore? NomeClasse nomeoggetto = new NomeClasse(); I costruttori si invocano soltanto con l operatore new. L operatore new riserva la memoria per l oggetto; il costruttore definisce il suo stato iniziale. Se non definiamo un costruttore per una classe, il compilatore genera un costruttore predefinito. Il costruttore predefinito di una classe: è pubblico e non richiede parametri inizializza tutte le variabili di esemplare: a zero le variabili di tipo numerico a false le variabili di tipo boolean al valore speciale null i riferimenti oggetto, in modo che tali variabili non si riferiscano ad alcun oggetto. Un costruttore appartiene all interfaccia pubblica: 1. ha uno specificatore di accesso public 2. ha sempre il nome della Classe Saluto 3. ha un eventuale elenco di parametri ( ) 4. ha un corpo {messaggio = Ciao ; 5. NON ha tipo di ritorno: NON è un metodo. Si possono avere uno o più costruttori. 3

Questa classe costruisce sempre lo stesso messaggio: Ciao. Vogliamo personalizzare il messaggio in modo che l utente possa inserire il suo nome; scriviamo un secondo costruttore che riceve come parametro il nome dell utente: public Saluto(String nome){ messaggio = Ciao + nome; public class Saluto{ //parte privata private String messaggio; //interfaccia pubblica public Saluto(){//primo costruttore messaggio = Ciao ; public Saluto(String nome){//secondo costruttore messaggio = Ciao + nome; public String ciao(){//metodo di accesso return messaggio; //fine classe Saluto Per sapere se il nostro concetto funziona bene dobbiamo costruire una classe di collaudo come se fossimo gli utenti della classe Saluto. Abbiamo due costruttori e quindi costruiremo (almeno) due oggetti (due esemplari della classe) e stamperemo i messaggi corrispondenti. Possiamo inserire nomi diversi nel secondo costruttore. public class ProvaSaluto{//classe di prova public static void main(string[] arg){ Saluto primo = new Saluto(); Saluto secondo = new Saluto( Eva ); Saluto terzo = new Saluto( Lorenzo ); System.out.println(primo.ciao()); System.out.println(secondo.ciao()); System.out.println(terzo.ciao()); //fine main //fine classe Sovraccarico (overloading). Abbiamo due costruttori con lo stesso nome ma con parametri diversi: il primo non ha parametri, il secondo ha un parametro di tipo String. Come funziona la scelta? Il compilatore verifica che il costruttore ci sia e sia coerente (il parametro o manca o è String) ed assegna il primo costruttore alla variabile primo e il secondo costruttore alle variabili secondo e terzo. Se esistono più costruttori in una classe, questi hanno tutti lo stesso nome, perché devono comunque avere lo stesso nome della classe: il compilatore decide quale costruttore invocare basandosi sul numero e sul tipo dei parametri forniti nell invocazione. Se si usa lo stesso nome, il nome diventa sovraccarico (nel senso di carico di significati diversi ): questo accade spesso con i costruttori. 4

Accade più di rado con i metodi; c è però un motivo ben preciso per farlo (ed è bene farlo in questi casi): usare lo stesso nome per metodi diversi (che richiedono parametri di tipo diverso) viene fatto per indicare che viene compiuta la stessa elaborazione ma su tipi di dati diversi. Abbiamo già visto questo sovraccarico con il metodo print che ha parametri di tipo diverso oppure non ha parametri. Cosa accade quando facciamo: Saluto secondo = new Saluto( Eva ); Si costruisce un oggetto di tipo Saluto: 1. viene attivato il secondo costruttore 2. il parametro nome prende il valore Eva 3. il campo del messaggio diventa la stringa Ciao Eva 4. new restituisce la referenza 5. la referenza è memorizzata in secondo secondo Ciao Eva Cosa accade quando facciamo: Saluto a = new Saluto(); Saluto b = new Saluto(); a e b sono due oggetti distinti: due esemplari della classe Saluto; essi contengono lo stesso messaggio (la stringa Ciao ) ma sono due aree di memoria diverse. Passaggio dei parametri Nella classe di prova abbiamo l istruzione Saluto secondo = new Saluto( Eva ); Nella classe Saluto abbiamo il costruttore public Saluto(String nome){ messaggio = Ciao + nome; Quando viene attivato il costruttore, la stringa Eva viene assegnata alla variabile stringa nome (parametro) del costruttore e quindi usata nell assegnazione successiva. Passaggio dei parametri Finchè non viene attivato il secondo costruttore, la stringa nome non ha valore. Ogni oggetto creato con il secondo costruttore ha la sua variabile nome che viene inizializzata nel momento in cui tale costruttore viene attivato Ciao Lorenzo Ciao Eva Compilazione Possiamo compilare la classe Saluto.java ed ottenere il bytecode Saluto.class. Questa è una buona regola: compilare la classe e verificare che almeno a livello di compilazione non ci siano errori. Possiamo compilare la classe di prova ProvaSaluto.java senza aver compilato la classe Saluto. Cosa accade? terzo secondo 5

Compilazione Quando il compilatore incontra l istruzione Saluto primo = new Saluto(); verifica che Saluto sia il nome di una classe: trova un file di nome Saluto.java che contiene una classe pubblica di nome Saluto. In tale modo la classe Saluto viene collegata alla classe di prova e compilata anch essa. Si possono compilare separatamente le classi che definiscono i nuovi tipi di dato. Quando si compila il programma di collaudo si compilano anche tutte le classi che ad esso sono agganciate (se non sono già state compilate). Categorie di variabili Realizzando classi incontriamo tre diverse categorie di variabili (par. 3.7) variabili di istanza (campi di esemplare) variabili parametro variabili locali Queste variabili si differenziano per: appartenenza, visibilità, inizializzazione, ciclo di vita. Variabili di istanza Una variabile di istanza: private String messaggio; appartiene all oggetto e ogni oggetto ne possiede una è visibile ai metodi ed ai costruttori della classe viene inizializzata dal costruttore, oppure ha una inizializzazione di default viene creata ( nasce ) quando l oggetto viene creato viene eliminata ( muore ) quando l oggetto viene eliminato (ossia non è più referenziato) o quando il main termina. Variabili parametro Una variabile parametro di un metodo o di un costruttore: (String[] arg) (String nome) appartiene al metodo è visibile all interno del metodo viene inizializzata all atto dell invocazione del metodo viene creata ( nasce ) quando il metodo viene invocato viene eliminata ( muore ) quando il metodo termina la sua esecuzione. Variabili locali Una variabile locale: int a; Saluto primo; appartiene a un metodo è visibile all interno del metodo deve essere esplicitamente inizializzata viene creata ( nasce ) quando viene eseguito l enunciato che la definisce: nometipo nomevar; viene eliminata ( muore ) quando l esecuzione del programma esce dal blocco in cui è stata definita. Il progetto BankAccount 6

Si vuole progettare una classe BankAccount che rappresenti un conto bancario (par. 3.2-3.6). Dobbiamo prima di tutto individuare quali sono le funzioni che questo concetto deve rappresentare: in un conto bancario noi possiamo versare dei soldi, prelevare dei soldi e richiedere il saldo. Pertanto il comportamento che deve avere un oggetto di tipo BankAccount sarà rappresentato da dei metodi: - versare denaro: deposit - prelevare denaro: withdraw - conoscere il saldo: getbalance Da che cosa è rappresentato un conto bancario? Qual è lo stato di un conto bancario? Un conto bancario è rappresentato dalla quantità di denaro presente al momento in cui lo si guarda: il saldo attuale. La classe BankAccount avrà come dato (campo, forma) il saldo: una variabile di istanza di nome balance. Una variabile di istanza ha: un nome un accesso un tipo di dato viene inizializzata esplicitamente o per default. Come nome della variabile si sceglie un nome che ne ricordi il significato; come tipo un valore reale; l accesso è bene che sia private : private double balance; Le variabili di esemplare sono di solito private perché in tale modo possono essere lette o modificate soltanto da metodi della classe a cui appartengono. Sono nascoste (hidden) al programmatore che utilizza la classe, e possono essere lette o modificate soltanto mediante l invocazione di metodi pubblici della classe (incapsulamento o information hiding). L incapsulamento ha dei vantaggi. Il vantaggio fondamentale è quello di impedire l accesso incontrollato allo stato di un oggetto, impedendo così anche che l oggetto venga (accidentalmente o deliberatamente) ad assumere uno stato incoerente. Il progettista della classe BankAccount potrebbe definire (ragionevolmente) che soltanto un saldo non negativo rappresenti uno stato valido per un conto bancario. Dato che il valore di balance può essere modificato soltanto invocando i metodi per depositare o prelevare denaro, il progettista può impedire che diventi negativo, magari segnalando una condizione d errore. Se invece fosse possibile assegnare direttamente un valore a balance dall esterno, sarebbe impossibile gestire gli eventuali errori (il saldo potrebbe diventare negativo anche senza prelievi). Per lo stesso motivo le uniche operazioni sono depositare e prelevare e non esiste un metodo con cui decidere il valore del proprio saldo. 7

Ciascun oggetto, esemplare o istanza, della classe ha una propria copia delle variabili di esemplare. Non c è alcuna relazione tra le varabili di esemplare di oggetti diversi. Ciascuna può essere modificata indipendentemente dall altra, così come ogni correntista ha un suo conto bancario ed un suo saldo. Possiamo decidere di aprire un conto con saldo iniziale 0, oppure con un saldo iniziale uguale ad un valore assegnato. Definiremo pertanto due costruttori. //primo costruttore public BankAccount(){ balance = 0; //secondo costruttore public BankAccount(double initialbalance){ balance = initialbalance; Anche in questa classe si hanno due costruttori: il compilatore effettua la risoluzione dell ambiguità. Se non trova un costruttore che corrisponda ai parametri forniti nell invocazione, segnala un errore semantico // NON FUNZIONA! BankAccount a = new BankAccount("tanti soldi"); cannot resolve symbol symbol : constructor BankAccount (java.lang.string) location : class BankAccount Per ogni metodo dobbiamo pensare a quale sarà: l accesso il tipo di dati restituito il nome gli eventuali parametri il corpo del metodo Dal momento che stiamo progettando il comportamento dell oggetto, infatti stiamo realizzando l interfaccia pubblica, i tre metodi avranno accesso public. Il metodo deposit deve permettere di depositare denaro; quindi avrà un parametro, double amount, e non dovrà restituire nulla. Il metodo withdraw deve permettere di prelevare denaro; in maniera analoga a deposit avrà un parametro, double amount, e non dovrà restituire nulla. Il metodo getbalance deve permettere di conoscere il saldo e quindi dovrà restituire un double che rappresenta il saldo e non avrà parametri. L intestazione di un metodo si chiama anche firma (signature). public class BankAccount{ private double balance; //primo costruttore public BankAccount(){ balance = 0; //secondo costruttore public BankAccount(double initialbalance){ balance = initialbalance; 8

public void deposit(double amount){ //realizzazione del metodo public void withdraw(double amount){ //realizzazione del metodo public double getbalance(){ realizzazione del metodo La realizzazione dei metodi di BankAccount è molto semplice: lo stato dell oggetto (il saldo del conto) è memorizzato nella variabile di esemplare balance quando si deposita o si preleva una somma di denaro, il saldo del conto si incrementa o si decrementa della stessa somma il metodo getbalance restituisce il valore del saldo corrente memorizzato nella variabile balance Per semplicità, questa realizzazione non impedisce che un conto assuma saldo negativo. Classe di prova per BankAccount public class BankAccount{ //dati e costruttori public void deposit(double amount){ double newbalance = balance + amount; balance = newbalance; public void withdraw(double amount){ balance = balance - amount; public double getbalance(){ return balance; /*Costruiamo una classe di prova che costruirà oggetti di tipo BankAccount*/ public class ProvaBankAccount{ public static void main (String[] arg){ BankAccount cliente1 = new BankAccount(); BankAccount cliente2 = new BankAccount(1000); cliente1.deposit(5000); cliente2.withdraw(300); System.out.println( il primo cliente possiede + cliente1.getbalance()+ euro ); System.out.println( il secondo cliente possiede + cliente2.getbalance()+ euro ); Conseguenza dell incapsulamento Poiché la variabile balance di BankAccount è private, non vi si può accedere da metodi che non siano della classe (errore semantico segnalato dal compilatore) /* codice interno ad un metodo che non appartiene a BankAccount */ double b = cliente1.balance; // ERRORE balance has private access in BankAccount double b = cliente1.getbalance(); // OK I parametri dei metodi public void deposit(double amount){ balance = balance + amount; Cosa succede quando invochiamo il metodo? cliente1.deposit(5000); L esecuzione del metodo dipende da due valori: il riferimento all oggetto cliente1 (parametro implicito) il valore 5000 (parametro esplicito) Quando viene eseguito il metodo, il suo parametro esplicito amount assume il valore 5000 (par. 3.8): public void deposit(double amount) 9

I parametri dei metodi Nel metodo vengono utilizzate due variabili: amount: è il parametro esplicito del metodo balance: è la variabile di esemplare della classe. Sappiamo che di tale variabile esiste una copia per ogni oggetto. Alla variabile balance di quale oggetto? Come si fa a sapere quale saldo viene incrementato? Il parametro implicito che invoca il metodo deposit è cliente1, pertanto è il balance di cliente1. Parola chiave this Per facilitare la comprensione e la lettura del codice riguardo all appartenenza della variabile di istanza ad un oggetto, si usa la parola chiave this. Si può scrivere: this.balance = this.balance + amount; Con l invocazione del metodo: cliente1.deposit(5000); il nome del parametro implicito cliente1 viene assegnato a this; ogni metodo ha sempre uno ed un solo parametro implicito (dello stesso tipo della classe a cui appartiene il metodo). Parola chiave this La vera sintassi del metodo dovrebbe essere public void deposit(double amount){ this.balance = this.balance + amount; // this ha il tipo del parametro implicito Algoritmi di Ricerca Solitamente non si usa perché this è uguale per tutti gli oggetti. Quando un metodo agisce su una variabile di esemplare, cliente1.deposit(5000), è il compilatore che costruisce un riferimento alla variabile di esemplare (balance) dell oggetto rappresentato dal parametro implicito (cliente1). Consideriamo un insieme di elementi (numeri, caratteri, stringhe, oggetti di un tipo di dato, ) e vogliamo rispondere alla domanda se un elemento dato appartiene oppure no all insieme. L idea per un simile algoritmo è quella di considerare uno ad uno gli elementi e di confrontarli con l elemento dato. Come possiamo considerarli tutti una ed una sola volta? Cosa significa essere uguali per numeri, stringhe, oggetti di tipo qualunque? Per prima cosa consideriamo una struttura di dati in cui inserire gli elementi: array. Gli elementi sono considerati in sequenza e quindi sappiamo che esiste un primo elemento, il successivo, l ultimo. Supponiamo, per ora, che questi elementi siano dei numeri: sappiamo, pertanto, cosa significa dire che due numeri a e b sono uguali o diversi. Vedremo poi cosa vuole dire che due oggetti (dello stesso tipo) sono uguali e come facciamo ad eseguire un confronto tra oggetti. 10

Problema. Sia A un array di numeri (interi, reali) e sia b un elemento dello stesso tipo di A. vogliamo rispondere alla domanda: b è un elemento di A? Analisi. A = (a 1, a 2, a n ) esiste un indice i (compreso tra 1 ed n) tale che a i = b? I caso. Gli elementi di A sono tutti distinti tra loro: se esiste l indice i tale che sia a i = b, esso è unico. Dobbiamo esaminare una sequenza di valori e per ognuno di essi ci chiediamo se a i == b Abbiamo quindi una struttura iterativa. Quale predicato governa la struttura? 1. Dobbiamo esaminare tutti i numeri: avremo un indice che scorre gli elementi dal primo all ultimo, passando al successivo. 2. Ci fermiamo quando lo abbiamo trovato (dopo non c è più, visto che sono tutti diversi tra loro). Abbiamo un predicato composto che diventa falso non appena uno dei due predicati che lo compongono risulti falso: pertanto si prosegue (finché ci sono numeri) e (finché non è trovato) Progetto. Per il primo predicato utilizziamo un indice che descrive tutti gli elementi; per il secondo predicato utilizziamo una variabile booleana trovato che inizialmente è falsa (l elemento può non essere presente) e che diventa vera se l elemento è presente. Scriviamo lo schema dell algoritmo, usando un linguaggio di pseudocodifica, poi andremo a verificare se la struttura iterativa risolve il problema dato. Algoritmo ricercalineare definizione variabili a array, b intero n, i intero trovato booleano acquisire e stampare n, le n componenti di a e il valore b i 0 trovato falso mentre i n e non trovato i i+1 se a[i] == b allora trovato vero eseguire //finescelta //fine ciclo mentre se trovato //P e Q: quale è diventato falso? allora stampa trovato al posto i altrimenti stampa elemento non presente //fine scelta //fine algoritmo Per verificare l algoritmo, costruiamo il tracciato (tracing) dei valori assunti dalle variabili durante l esecuzione del programma su una particolare scelta di dati (processo). Costruiamo una tabella dopo aver assegnato dei valori ad n, A e b. Quando si prova un programma, questo tracciato si ottiene eseguendo della stampe dei valori della variabili. n = 5 A = (7, 1, -3, 0, 4) b = 0 11

Tracing Tracing n 5 i 0 trovato F b = 0 n 5 i 0 trovato F b = 15 i n sì sì sì sì sì non trovato V V V V F P V V V V F il ciclo i 1 2 3 4 termina a[i] 7 1-3 0 i=4 a[i] == b no no no sì trovato = V trovato F F F V iterazione 1 2 3 4 i n sì sì sì sì sì no non trovato V V V V V V P V V V V V F il i 1 2 3 4 5 ciclo a[i] 7 1-3 0 4 termina a[i] == b no no no no no i = 5 trovato F F F F F trovato = F iterazione 1 2 3 4 5 Codifica Gli array in Java hanno un indice che inizia da 0. Nella maggior parte dei problemi la sequenza inizia da 1; è meglio iniziare da 1 o da 0 se si vuole scrivere l algoritmo nel linguaggio di programmazione? Iniziare da 1 significa lasciare un posto vuoto a sinistra della prima componente che mai andrà utilizzato, diversamente da quelli vuoti a destra (nel caso in cui n<dimensione); il numero massimo di elementi allora sarà n=dimensione-1. Iniziando da 1 posizione ed ordinale coincidono: il primo è al posto 1, il secondo al posto 2, Codifica In previsione di utilizzare le tecniche di raddoppio per gestire array, come se l array avesse lunghezza variabile, conviene iniziare da 0, e ricordare che il primo elemento è al posto 0, il secondo al posto 1, Cosa cambia nell algoritmo? Gli elementi saranno: a 0, a 1,, a n-1 e pertanto i -1 mentre i n-1 e non trovato Oppure possiamo definire due variabili intere: inizio, fine (primo, ultimo) a cui attribuire i valori voluti. Codifica //definizione delle variabili //acquisire e stampare i dati: acquisizione da 0 trovato = false; i = -1; while((i!= n-1) && (!trovato)){ i++; if(a[i] == b) trovato = true; if(trovato) System.out.println( trovato al posto + i); else System.out.println( elemento non presente ); Varianti Possiamo anche iniziare dall indice che corrisponde al primo valore dell array. Come cambiano allora il predicato e l incremento, data la relazione tra essi? i inizio trovato falso mentre i fine+1 e non trovato eseguire se a[i] == b allora trovato vero altrimenti i i+1 //finescelta //fine ciclo mentre //con inizio = 0 e fine = n-1 oppure inizio = 1 e fine = n 12

Varianti Abbiamo messo subito il confronto perché il primo elemento è subito disponibile. Abbiamo messo l incremento di i in alternativa, perché viene eseguito solo se il predicato è falso. Potevamo mettere l incremento in sequenza, dopo finescelta? Nel caso di elemento trovato, l indice i non indica più la posizione, ma quella successiva. Pertanto o si stampa i-1, o si assegna ad altra variabile posiz il valore dell indice nel caso vero, o l importante è sapere che una operazione in sequenza ad una if viene eseguita con predicato vero e con predicato falso. Varianti Possiamo anche scrivere il predicato senza fare uso della variabile logica trovato. L uso delle variabili logiche è per migliorare la comprensione dell algoritmo. Una variabile logica occupa poco posto e non necessita di confronti: il suo valore è già true oppure false (è solo un accesso). Esercizio. Riscrivere l algoritmo senza fare uso della variabile logica trovato: si dovrà inserire nel predicato il confronto a[i]!= b 13