Interfacce

Multi-Ereditarietà

class Knife {
  void cut() {
    ...

  }
}

class Fork {
  void pick() {
    ...
  }
}
Come si definisce il tipo SwissKnife:
class SwissKnife extends Fork,Knife {
  void cut() {
    ...
  }
  void pick() {
    ...
  }
}
ma questo non è possibile. In Java, si può estendere solo un tipo.

Interface

Java propone la nozione di interface
interface Cutable {
  void cut();
}
Tale dichiarazione è equivalente alla seguente definizione:
abstract class Cutable {
  public void cut();
}
Tutti i metodi di una interfaccia possono essere solo pubblici.

Cosí come una class può estendere un'altra class, una class può implementare una interfaccia:

class Knife implements Cutable {
  void cut() {
    ...

  }
}
Adesso Cutable è un tipo possibile per un oggetto di tipo Knife. Questo è valido:
Cutable f = new Knife();
e (new Knife()) instanceof Cutable è vero.

Possiamo fare lo stesso gioco per il Fork

interface Pickable {
  void pick();
}
class Fork implements Pickable {
  void pick() {
    ...
  }
}
Adesso il punto importante è che una class può implementare più di una interfaccia:
class SwissKnife implements Cutable, Pickable {
  void cut() {
    ...
  }
  void pick() {
    ...
  }
}

Costante

Non si possono definire campi dentro un'interfaccia, solo costanti:
interface Size {
  static final SMALL =1;
  static final MEDIUM =2;
  static final LARGE =3;
}

class A implements Size {
  int method (int size) {
    switch (size) {
      case SMALL: ...
        ...
    }
}

Sotto interfaccia

Come per le class, si possono estendere le interfacce:
interface A {
  int method1();
}
interface B extends A {
  int method2();
}

Selezionare i metodi

Le regole sono le stesse di quelle per le class. Prima si sceglie staticamente il metodo. Dopo è il tipo dinamico dell'oggetto sul quale è applicato il metodo che determina il codice eseguito.

Callbacks

Una applicazione importante delle interfacce sono i cosidetti callbacks. Permettono di implementare elegantemente i pointers. Esempio:
class Appointment {
  Date date;
  String info;
}
class Agenda {
  void addAppointment(Appointment a) {
    ...
  }
  void cancelAppointment(Appointment a) {
    ...
  }
  void moveAppointment(Appointment a) {
    ...
  }
}
Per condividere un'agenda, bisogna che le persone che condividono l'agenda possano essere avvertite delle modifiche. Prima si definisce una interfaccia con un metodo per avvertire di una modifica:
interface AgendaUser {
  void update (Appointment a);
}
Secondo, si usa il tipo AgendaUser per manipolare dentro Agenda gli utenti da avvertire:
class Agenda {
  AgendaUser[] users;
  void addUser(AgendaUser u) {
    ...
  }
  void addAppointment(Appointment a) {
    ...
    for(i=0; i< users.length; i++) {
      users[i].update(a);
    }
  }
  ...
}
Infine, quando si definisce una class che sia un utente dell'agenda, è sufficiente dire che questa class implementa AgendaUser e implementare il metodo update:
class A implements AgendaUser {
  A(Agenda a) {
    a.addUser(a);
  }
  void update(Appointment a) {
    ...
  }
  ...
}

Laurent Théry
Last modified: Wed May 8 01:05:00 MEST 2002