Interfacce


Java Sun

Earthweb
(ex Gamelan)

Jars

Java Boutique

JavaWorld

PIP






  JSem: 3.4

   Un tipico esempio di interfaccia è il telecomando del televisore: premendo vari pulsanti l'utente può regolare il volume, l'immagine, cambiare canale, ecc... senza avere bisogno di sapere come questi metodi vengono effettivamente implementati, in altri termini l'utente non ha bisogno di conoscere i meccanismi interni del televisore (nè il modo in cui il telecomando comunica con i circuiti del televisore).
Un altro tipo di interfaccia, omnipresente in programmazione, sono le GUI (Graphical User Interface), per esempio la finestra del vostro browser con i suoi vari pulsanti è una GUI.
Più generalmente (e più astrattamente), si potrebbe dire che la lingua italiana è un'interfaccia tra due persone (italiane!). In questo senso la nozione di interfaccia è abbastanza vicina a quella di protocollo. Per esempio il protocollo http permette a due computers su Internet di comunicare: in pratica i due computers si accordano sui metodi da usare per scambiarsi le informazioni.


    Un'interfaccia Java definisce dei metodi ma senza implementarli. Una classe che implementa l'interfaccia accetta di implementare tutti i metodi dell'interfaccia, pertanto accetta un certo tipo di comportamento ("protocollo").
Si potrebbe dire che un'interfaccia è una classe astratta i cui metodi sono tutti astratti; questo è inesatto perchè un'interfaccia non è una classe (come vedremo, questo è essenziale), ma rende l'idea: ogni "estensione" (nel caso specifico implementazione) deve definire tutti i metodi dell'interfaccia.
La sintassi per dichiarare un'interfaccia è:

accesso interface  Nome{
//metodi
tipo ritorno	nome1(elenco parametri);
.............................
tipo ritorno	nomeN(elenco parametri);
//variabili
tipo	nome1 = valore;
.............
tipo	nomeM = valore;
}

qui accesso è public o di default quando omesso (quando l'accesso è di default, l'interfaccia è disponibile nel pacchetto in cui viene dichiarata).
I metodi sono tutti astratti (quindi senza corpo).
Le variabili sono implicitamente final e static, cioè non possono essere modificate dalla classe di implementazione. Le variabili devono essere inizializzate con un valore.

Esempio:
Riprendiamo le nostre forme geometriche: vorremmo definire delle classi di forme geometriche con certi metodi (draw e area), inoltre vorremmo che queste classi derivassero da una classe (astratta) origine (l'origine della forma: il lato sinistro alto del rettangolo nel quale viene designata la forma). Possiamo realizzare questo programma con un'interfaccia InterForme e una classe Origine:
Definzione dell'interfaccia:

import java.awt.Graphics;

public interface InterForme{

// metodi
int Area();
void Draw(Graphics g);

}

come al solito, salvare questo file come InterForme.java e compilarlo.
La classe Origine:

class Origine{

int ox, oy;

//costruttore
Origine(int ox, int oy){
	this.ox = ox;
	this.oy = oy;
	}
}

La classe RettOr che estende Origne e implementa InterForme:

import java.awt.Graphics;

class RettOr extends Origine implements InterForme{

int w,h;

//costruttore

RettOr(int ox, int oy, int w, int h){
	super(ox, oy);
	this.w = w;
	this.h = h;
	}
//implementare metodo area dell'interfaccia
 
public int Area(){
	return w*h;
	}
//implementare metodo draw dell'interfaccia

public void Draw(Graphics g){
	g.drawRect(ox,oy,w,h);
	}
}

Finalmente un'applet per testare tutto quanto:

import java.applet.*;
import java.awt.*;

public class RettOrDemo extends Applet{

RettOr R = new RettOr(10,10,30,50);

public void paint(Graphics g){
	R.Draw(g);
	g.drawString("L'area è: " +R.Area(),10, 90);
	}
}

L'outpout è quello che pensate (verificatelo!).
Chiaramente, nel caso specifico, questa è una grande complicazione per il risultato ricercato, ma vedremo altre situazioni in cui la nozione d'interfaccia semplifica notevolmente le cose.

Osservazione: Quando si implementa un metodo di interfaccia, esso deve essere dichiarato public.

Un'interfaccia può estenderne un'altra, la sintassi è simile a quella dell'estensione delle classi:
interface A{
.....
}

interface B extends A{
.....
}

Una classe che implementa B deve definire tutti i metodi di B, vale a dire quelli di A e quelli dichiarati in B.


   Differenza tra classi astratte ed interfacce.

Come già osservato, un'interfaccia è simile ad una classe astratta con soli metodi astratti, ma allora perchè non usare classi astratte?
Un primo motivo molto semplice: in Java una classe può estendere una sola classe. Nell'esempio precedente se la classe RettOr estende Origine, non può estendere una classe MetForme. Una classe però può implementare un numero qualsiasi di interfacce. Nell'esempio, RettOr non può estendere una classe MetForme, ma può implementare un'interfaccia InterForme.
Quindi la nozione di interfaccia risolve il problema della multiereditarietà.
Ma, e questa è la seconda motivazione, lo risolve in modo particolare. In un processo di multiereditarietà, solo le classi correlate, di una stessa famiglia, erediterano di specifici metodi; una stessa interfaccia, invece, può essere implementata da più classi, non necessariamente correlate. L'interfaccia ha un raggio d'azione trasversale rispetto all'ereditarietà. In breve: "stessa interfaccia, metodi multipli", questo è un altro aspetto del polimorfismo.
Tra le interfacce più usate in Java abbiamo, per esempio ActionListener (per gli eventi), Runnable(per i Threads).




 next		content		previous