"Ciao, Amigo! Oggi farai delle scoperte. L'argomento di oggi—rullo di tamburi, per favore—sono le interfacce. "

"Sì. Una giornata così meravigliosa che sto tornando a casa per farmi un bagno."

" Un'interfaccia è figlia dell'astrazione e del polimorfismo. L'interfaccia è molto simile a una classe astratta in cui tutti i metodi sono astratti. Viene dichiarata allo stesso modo di una classe, ma con la parola chiave . Ecco alcuni esempi: interface"

Codice Descrizione e fatti
interface Drawable
{
void draw();
}
interface HasValue
{
int getValue();
}
1) Invece della parola class, scriviamo interface.

2) Contiene solo metodi astratti (non è necessario aggiungere la parola abstract).

3) Infatti tutti i metodi sulle interfacce sono pubblici.

interface Element extends Drawable, HasValue
{
int getX();
int getY();
}
Un'interfaccia può ereditare solo altre interfacce.

Puoi avere molte interfacce genitore.

class abstract ChessItem implements Drawable, HasValue
{
private int x, y, value;

public int getValue()
{
return value;
}

public int getX()
{
return x;
}

public int getY()
{
return y;
}

}
Una classe può ereditare diverse interfacce (e solo una classe). Per mostrare questa eredità, usiamo la parola chiave  implements.

La ChessItem classe è stata dichiarata astratta: ha implementato tutti i metodi ereditati tranne draw.

In altre parole, ChessItem contiene un metodo astratto:  draw().

"Interessante. Ma perché abbiamo bisogno di interfacce? Quando vengono utilizzate?"

"Le interfacce hanno due forti vantaggi rispetto alle classi:"

1) Separazione delle "definizioni del metodo" dalle implementazioni del metodo.

In precedenza ti ho detto che se vuoi consentire ad altre classi di chiamare i metodi della tua classe, devi contrassegnarli comepublic . Se vuoi che determinati metodi vengano chiamati solo dalla tua classe, allora devono essere contrassegnati con private. In altre parole, dividiamo i metodi della classe in due categorie: «per tutti» e «solo per me».

Possiamo usare le interfacce per rafforzare ancora di più questa separazione. Faremo una "classe per tutti" speciale che erediterà una seconda "classe solo per me". Sembrerebbe più o meno così:

Prima
class Student
{
 private String name;

 public Student(String name)
 {
  this.name = name;
 }

 public String getName()
 {
  return this.name;
 }

 private void setName(String name)
 {
  this.name = name;
 }
Dopo
interface Student
{
 public String getName();
}

class StudentImpl implements Student
{
 private String name;
 public StudentImpl(String name)
 {
  this.name = name;
 }
 public String getName()
 {
  return this.name;
 }
 private void setName(String name)
 {
  this.name = name;
 }
}
Prima
public static void main(String[] args)
{
 Student student =
               new Student("Alibaba");
 System.out.println(student.getName());
}
Dopo
public static void main(String[] args)
{
 Student student =
               new StudentImpl("Ali");
 System.out.println(student.getName());
}

Abbiamo diviso la nostra classe in due parti: un'interfaccia e una classe che implementa l'interfaccia.

"Allora qual è il vantaggio?"

"La stessa interfaccia può essere implementata da (ereditare) classi diverse. E ogni classe può avere il proprio comportamento. Proprio come ArrayList e LinkedList sono due diverse implementazioni dell'interfaccia List. "

Pertanto, stiamo nascondendo non solo le diverse implementazioni, ma anche le classi che contengono le implementazioni (possiamo semplicemente utilizzare le interfacce ovunque nel codice). Ciò ci consente di sostituire in modo molto flessibile alcuni oggetti con altri oggetti mentre il programma è in esecuzione, modificando il comportamento di un oggetto all'insaputa di nessuna delle classi che lo utilizzano.

In combinazione con il polimorfismo, questa è una tecnica molto potente. Al momento, è tutt'altro che ovvio il motivo per cui dovremmo farlo. Devi prima incontrare programmi composti da dozzine o centinaia di classi per apprezzare come le interfacce possono semplificare notevolmente la tua vita.

2) Ereditarietà multipla.

In Java, ogni classe può avere solo una classe genitore. In altri linguaggi di programmazione, le classi possono spesso avere diverse classi genitore. Questo è molto comodo, ma crea anche molti problemi.

Java offre un compromesso:   non puoi ereditare più classi, ma puoi implementare più interfacce. Un'interfaccia può avere diverse interfacce padre.  Una classe può implementare più interfacce ed ereditare solo una classe genitore.