Disegno di interfacce

Nella precedente certificazione abbiamo studiato come dichiarare un interfaccia, come estenderla e come implementarla.

Possiamo ricapitolare dicendo che un interfaccia è un tipo astratto di dati simile ad una classe che definisce solo metodi astratti e public che ogni classe che implementa deve definire.

Un interfaccia può anche definire costanti (public static) e da Java 8 anche metodi statici e metodi con implementazione di default.

Vediamo un breve e semplice esempio di un interfaccia e della sua implementazione :

public interface Aereomobile {
  public int aperturaAlare() throws Exception;
  public static final int VELOCITA_MAX = 450;
  public default void atterra() {
    System.out.println("l'aereo sta atterrando");
  }
  public static double calcolaVelocita(float distanza, double tempo) {
    return distanza / tempo;
  }
}

public class Boeing747 implements Aereomobile {
  public int aperturaAlare() {
    return 80;
  }
  public void atterra() {
    System.out.println("Boeing 747 sta atterrando");
  }
}

In questo esempio, il primo metodo definito nell’interfaccia è un metodo astratto, come possiamo vedere, questo rilancia una Exception, ma la classe Boeing747 che ne fa l’override non ha la clausola throws nella firma del metodo, se ci ricordiamo le regole dell’override, il metodo overridato non è obbligato a rilanciare l’eccezione.

La seconda dichiarazione VELOCITA_MAX è una costante, poi c’è un metodo atterra dichiarato come default, fornendo un implementazione di default alle classi concrete che non intendono overridarlo.

l’ultimo, fornisce un metodo statico, come per la costante VELOCITA_MAX è accessibile senza un istanza di una classe concreta.

Ricordiamo che le interfacce possono estendere altre interfacce, ereditandone tutti i metodi astratti.

public interface Aereo {
  public boolean isTurboElica();
}
public interface Jet extends Aereo {
  public void turnOnEngine();
}
public class Md80 implements Jet {
  public boolean isTurnoElica() { return false; }
  public void turnOnEngine() { System.out.println("Engine is starting"); }
}

Come vediamo, la classe concreta Md80 è obbligata a implementare tutti i metodi definiti in Aereo e Jet

Resta inteso, come è ovvio, che un interfaccia non può estendere una classe o implementare un interfaccia !

Ricordiamo che una classe in Java può implementare più di un interfaccia introducendo di fatto l’ereditarietà multipla in Java 8 con i metodi default, immagina di avere due interfacce che definiscono lo stesso metodo default, se una classe implementa entrambe le interfacce, il compilatore quale di questi due metodi utilizzera ? semplice, nessuno, ti obbligherà a overridarlo !

Scopo di un interfaccia

Le interfacce permetto di sviluppare codice senza doversi preoccupare di come è implementato realmente, facilita lo sviluppo in parallelo di applicazioni grandi, immagina di avere due team di sviluppo, uno che sviluppa in front end ed un altro che si occupa di implementare i servizi di backend, una volta stabilite le interfacce per le API, i due gruppi possono procedere in parallelo, il team del frontend potrà sviluppare il suo codice utilizzando le interfacce anche se l’implementazione non è ancora completata.

Ricordiamo di seguito, le regole basi da tenere sempre in mente quando si parla di interfacce:

  • le interfacce non possono estendere classi, ne le classi possono estendere le interfacce
  • le interfacce non possono essere dichiarate final
  • le interfacce non possono essere istanziate direttamente
  • se una classe implementa due interfacce che definiscono lo stesso metodo default, il compilatore ti obbliga a ridefinirlo