![]() ![]() |
|
![]() ![]() |
Un metodo astratto è
un metodo senza corpo, con un ";" dopo l'intestazione.
Una interfaccia (interface) in Java ha una struttura simile a una classe, ma può contenere SOLO costanti e metodi d'istanza astratti (quindi non può contenere né costruttori, né variabili statiche, né variabili di istanza, né metodi statici). Ad esempio, questa è la dichiarazione dell'interfaccia java.lang.Comparable (in Java 1.4, prima che fossero introdotti i tipi generici):
Spesso l'interfaccia comprende anche una descrizione
informale del significato dei metodi (che chiameremo specifica o contratto).
Ad esempio, nella API di Comparable
[locale,
Medialab,
Sun]
si vede che al metodo compareTo
è associata una precisa interpretazione (descritta a parole): esso definisce un
ordinamento totale sugli oggetti della classe. Sotto è riportato un estratto della specifica di compareTo:
|
![]() ![]() |
|
![]() ![]() |
Si può dichiarare che una classe implementa (implements) una data interfaccia: in questo
caso la classe deve fornire una realizzazione per tutti i metodi astratti
dell'interfaccia, cioè la classe deve fornire metodi con la
stessa firma descritta nell'interfaccia (e con il corpo,
naturalmente). La realizzazione di un metodo deve anche rispettare la
"specifica" del corrispondente metodo astratto.
Ad esempio, la seguente classe Intero (una versione semplificata di Integer) implementa Comparable rispettando la specifica di compareTo.
|
![]() ![]() |
|
![]() ![]() |
Le interfacce possono essere utilizzate:
|
![]() ![]() |
|
![]() ![]() |
La classe Max
fornisce il metodo max che restituisce il
massimo elemento di un array di Comparable, usando il metodo
compareTo per
confrontare gli oggetti:
La classe MaxInteroTest usa Max.max per stampare il massimo di un array di Intero: questo è possibile perché Intero implementa Comparable.
La classe MaxStringTest usa invece Max.max per stampare il massimo di un array di String: infatti anche String implementa Comparable.
Analogamente, sfruttando l'interfaccia Comparable, si possono scrivere algoritmi di ordinamento generici, applicabili a istanze di qualunque classe che la implementi. |
![]() ![]() |
|
![]() ![]() |
Nell'uso delle interfacce in un programma, ricordarsi
delle seguenti regole:
|
![]() ![]() |
|
![]() ![]() |
Si dichiara come una classe, ma con la parola
chiave interface (al posto di class):
Si noti che:
|
![]() ![]() |
|
![]() ![]() |
|
![]() ![]() |
|
![]() ![]() |
Come sappiamo, in Java ogni classe definisce un
tipo
di dati, i cui elementi
sono le istanze della classe (la cui struttura è determinata dalle
variabili d'istanza), e le cui operazioni
sono i metodi.
Una interfaccia definisce invece un tipo di dati astratto, di cui fornisce la specifica delle operazioni: la struttura dei suoi elementi e il modo in cui le operazioni sono effettivamente definite verrà determinato dal tipo di dati (la classe) che realizza (implements) l'interfaccia. Esempio: L'interfaccia List [locale, Medialab, Sun] e le classi ArrayList e Vector. |
![]() ![]() |
|
![]() ![]() |
Le interfacce forniscono un supporto linguistico
alla nozione di contratto tra chi usa gli oggetti di una classe,
e chi realizza la classe stessa.
Inoltre la classe che implementa l'interfaccia può essere sostituita con un'altra più efficiente (o più conveniente...), senza modificare il programma che la utilizza. |
![]() ![]() |
|
![]() ![]() |
Si possono usare le interfacce per associare alle classi una
certa proprietà, nel modo seguente:
Si osservi che con questo meccanismo, una proprietà viene ereditata
dalle sottoclassi (se una classe implementa un'interfaccia, tutte
le sue sottoclassi la implementano).
L'interfaccia Cloneable
[locale,
Medialab,
Sun] viene
utilizzata per determinare se un oggetto può essere clonato
oppure no. Si guardi la documentazione del metodo
clone() di
Object [locale,
Medialab,
Sun].
L'interfaccia java.io.Serializable viene
utilizzata per determinare se un oggetto può essere serializzato
oppure no. Vederemo la serializzazione di oggetti in seguito.
|