Ripasso su Java
Introduzione
• Per risolvere problemi complessi,
i linguaggi di programmazione forniscono costrutti
per
• realizzare nuove funzioni che trasformino un
insieme di argomenti di ingresso in un insieme di
risultati
• definire nuovi tipi di dato, ovvero collezioni di dati
strutturati con relative operazioni
Programmazione orientata agli oggetti
• In Java entrambe le funzionalita’ sono
realizzate da CLASSI
• nuove funzioni (procedure stand-alone) sono
realizzate da metodi statici
• nuovi tipi di dato sono realizzati tramite
variabili e metodi d’istanza che definiscono
lo stato interno degli oggetti e le relative
operazioni
Che cosa e’ una funzione?
• mapping da un insieme di input in un insieme di
output
• se consideriamo un tipo primitivo come
int abbiamo delle funzioni primitive, per esempio la
somma
int x=4;
int y=6;
int w=x+y;
• stiamo chiamando una funzione primitiva +, che
presi due parametri di tipo int resituisce la somma
Il ruolo dei metodi statici
• Per risolvere problemi complessi le operazioni primitive
del linguaggio non possono essere sufficienti
• Nuove funzioni si programmano tramite opportuni metodi
statici
public static int fact(int x){
//REQUIRES: x>0
// EFFECTS: ritorna x!
if (x==1) return 1;
return x * fact(x-1);}
Che cos’e’ un tipo di dato?
• un insieme di dati con delle operazioni che
permettono la lettura e/o modifica dei valori
• tipi di dato primitivi di Java,
int
String
arrays
• Le operazioni relative sono quelle fornite da Java
Nuovi tipi di dato
• Per risolvere problemi complessi i tipi di dato
primitivi non sono sufficienti
• Nuovi tipi di dato si programmano definendo una
classe in cui
---le variabili d’istanza definiscono lo stato interno
---i metodi d’istanza ed i costruttori definiscono le
operazioni
Esempio
• Vogliamo realizzare una classe BankAccount
i cui oggetti sono dei semplici conti bancari.
• Vogliamo le seguenti operazioni
 depositare denaro
 prelevare denaro
 chiedere il saldo corrente
Una possibile implementazione
public class BankAccount
{
public double balance;
//il saldo corrente
// costruttore
public BankAccount(double initial){
balance=initial;
}
Una possibile implementazione
// metodi
public void deposit(double amount) {
balance = balance + amount;
}
public void withdraw(double amount) {
balance = balance - amount;
}
public double getBalance() {
return balance;
}
}
Di cosa ci occupperemo?
• Il primo modulo di LIP si e’ concentrato sulla
progettazione di metodi statici e sui tipi primitivi
• Ci concentreremo ora sull’uso delle classi
per definire nuovi tipi di dato, tramite oggetti
• Introdurremo un concetto fondamentale per
estendere/modificare le classi: ereditarieta’
Procedure Stand-Alone: esercitazione
• Esercitazione di ripasso: metodi statici per arrays
• Introduremo un concetto nuovo: la differenza tra la
specifica e l’implementazione
• Cominceremo a vedere a cosa serve
• Nel caso per ora della definizione di procedure
stand alone
Specifica ed Implementazione
• Specifica (o interfaccia pubblica) descrive cosa una
classe fa (non come!!!!)
• L’implementazione e’ il codice dei metodi (ovvero
come il modo in cui si arriva al risultato richiesto)
• La specifica in Java si realizza tramite commenti
informali al codice
Come e’ fatta la specifica?
• “scheletro” della classe formato da
1. headers dei metodi pubblici
2. commenti informali che descrivono le proprieta’ dei
metodi, ovvero la relazione tra gli inputs ed i risultati
(gli input sono i parametri ma anche quelli impliciti se ci sono
modifiche esterne)
•
manca il codice del corpo dei metodi (implementazione)
In particolare
I metodi statici sono corredati da commenti
informali che descrivono il loro comportamento
(1) precondizione (REQUIRES)
(2) postcondizione (EFFECTS)
(3) eventuali modifiche (MODIFIES)
Un esempio di specifica
public class ProcArrays{
//OVERVIEW: la classe fornisce procedure utili per
// manipolare arrays di interi
• OVERVIEW: riporta informazioni generali sulla classe
Metodi di Ricerca I
public static int cerca(int [] a,int x){
\\EFFECTS:
restituisce il numero di occorrenze
\\ di x in a (eventualmente 0)}
• EFFECTS (post-condizione): descrive le proprietà degli outputs e le
eventuali modifiche effettuate su tutti gli inputs
Metodi di Ricerca II
public static int cercaord(int [] a,int x){
\\REQUIRES: a e’ ordinato in ordine crescente
\\EFFECTS:
restituisce il numero di occorrenze di x in a
(eventualmente 0)}
• REQUIRES (pre-condizione) impone vincoli sull’input
• Possono essere implementati nello stesso modo (il metodo
che funziona per quelli non ordinati funziona anche per
quelli ordinati (non vice-versa)
• Ma sfruttando l’ordinamento si ottiene una soluzione piu’
efficiente
Metodi Modificatori
public static void incr(int [] a, int x){
\\MODIFIES :a
\\EFFECTS:
modifica a, incrementando tutti i
valori di x }
• MODIFIES: riporta tutti gli inputs che potrebbero essere
modificati
Metodi Modificatori
public static int [] append(int [] a, int [] b){
\\EFFECTS:
restituisce un array che e’ la
concatenazione di a e b, ESEMPIO: a=[3,2,6],
b[9]====> ab=[3,2,6,9]}
• Se MODIFIES non e’ presente non devono essere modificati gli
argomenti
• Attenzione al passaggio dei parametri!
Metodi di Confronto
public static boolean subsequence(int [] a,int [] b){
\\EFFECTS:restituisce true se a e’ una sottosequenza
\\ di b, false altrimenti}
Esempio: a=[4,3] b=[4,1,8,3]
a=[4,3] b=[3,8,4]
SI
NO
tutti gli elementi di a compaiono compaiono in b nello
stesso ordine relativo, (cioè se e solo se formano una
sottosequenza di elementi anche non consecutivi di b,
ottenuta cancellando alcune posizioni di b).
Implementazione
• Che dovrete fare per esercizio
• Codice del corpo dei metodi statici
• Deve soddisfare la specifica
Osservazione
• Diverse implementazioni possono soddisfare la
stessa specifica
public static int cerca(int [] a,int x){
\\EFFECTS:
restituisce il numero di occorrenze
\\ di x in a (eventualmente 0)
int num=0;
for (int i=0; i < a.length; i++)
{ if (a[i]==x} num++;}
return num;}
Osservazione
• Diverse implementazioni possono soddisfare la
stessa specifica
public static int cerca(int [] a,int x){
\\EFFECTS:
restituisce il numero di occorrenze
\\ di x in a (eventualmente 0)
int num=0;
for (int i=a.length-1; i >=0 ; i--)
{ if (a[i]==x} num++;}
return num;
}
Diverse Implementazioni
• Nell’esempio precedente le due
implementazioni restituiscono lo stesso
risultato
• Diverse implementazioni corrette della
stessa specifica possono anche dare risultati
differenti
public static int search (int[] a, int x)
// EFFECTS: se x occorre in a,ritorna un
// indice in cui occorre, altrimenti -1
{ if (a==null) return -1;
for (int i=0; i < a.length; i++)
{if (a[i]==x return i;}
return -1;}
{ if (a==null) return -1;
for (int i=a.length-1; i >= 0; i--)
{if (a[i]==x return i;}
return -1;}
A cosa serve la specifica?
• ci permette di astrarre dalla computazione
descritta nel corpo della procedura
(dall’implementazione)
• in uno stile di programmazione corretto chi usa la
procedura deve vedere cosa fa (la specifica) e non
come lo fa (l’implementazione)
Il punto di vista di chi usa la procedura
public static int search (int[] a, int x)
// EFFECTS: se x occorre in a,ritorna un
// indice in cui occorre, altrimenti -1
• gli utenti della procedura vedono “solo” la specifica
• gli utenti della procedura non possono osservare le
computazioni descritte dal corpo e dedurre da questo
proprietà diverse da quelle specificate dalle asserzioni
– per esempio che ritorna il primo o l’ultimo indice in cui x
occorre
Vantaggi
•
•
Se la specifica e l’implementazione sono progettati in
modo opportuno, ovvero sono chiaramente separate e
l’implementazione e’ invisibile a chi usa la procedura
si rende l’implementazione della procedura
indipendente dai moduli che la usano
1. l’implementazione per esempio puo’ essere cambiata
senza modificare il codice dei moduli che la usano
2. si rendono i vari moduli di un programma il piu’
possibile indipendenti
Testing
• In parallelo alla classe sviluppare un programma
main che fa il testing
• Creare degli arrays (magari prendendo valori da
tastiera)
• Applicare i metodi e verificare i risultati (tramite
stampa)
• Testare i casi significativi. P.e. nei metodi booleani
un caso in cui vale ed uno in cui non vale
Scarica

Lucidi