English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

教程基础Java

Java Controllo di flusso

Java Array

Java Orientamento ad oggetti (I)

Java Orientamento ad oggetti (II)

Java Orientamento ad oggetti (III)

Gestione delle eccezioni Java

Java List

Java Queue (coda)

Java Map collection

Java Set collection

Java Input/Output (I/O)

Java Reader/Writer

Altri argomenti Java

Interfaccia Java (Interface)

In questo tutorial, impareremo Java interfaccia. Impareremo a implementare un'interfaccia e quando usarla con esempi.

In Java, un'interfaccia definisce un insieme di specifiche che altre classi devono implementare. Ad esempio,

interface Polygon {
   public void getArea();
{}

Qui Polygon è un'interfaccia. Abbiamo usato la parola chiave interface per dichiarare un'interfaccia.

Il metodo getArea() è la specifica definita nell'interfaccia Polygon. Tutte le classi che utilizzano questa interfaccia devono implementare il metodo getArea().

Un'interfaccia può includere metodi astratti e costanti. Ad esempio,

interface Polygon {
   public static final String colore = "blue";
   
   public void getArea();
{}

Nell'esempio sopra, abbiamo creato un'interfaccia Polygon. Include una variabile costante colore e un metodo astratto getArea().

È importante notare che tutti i metodi all'interno dell'interfaccia sono implicitamente public, e tutti i campi sono implicitamente public static final. Pertanto, non è necessario specificare l'access modifier all'interno dell'interfaccia. Ad esempio, possiamo scrivere il codice come

interface Polygon {
   String colore = "blue";
   
    void getArea();
{}

Interfaccia e parola chiave implements

Come un'astrazione, non possiamo creare oggetti di un'interfaccia. Ma possiamo implementare un'interfaccia in altri classi. In Java, usiamo la parola chiave implements per implementare un'interfaccia. Ad esempio,

interface Polygon {
    void getArea(int lunghezza, int larghezza);
{}
class Rectangle implements Polygon {
    public void getArea(int lunghezza, int larghezza) {
        System.out.println("L'area del rettangolo è " + (lunghezza * larghezza));
    {}
{}
class Main {
    public static void main(String[] args) {
        Rectangle r1 = new Rectangle();
        r1.getArea(5, 6);
    {}
{}

Risultato di output

L'area del rettangolo è 30

Nel programma sopra, abbiamo creato un'interfaccia Polygon. L'interfaccia Polygon ha un metodo astratto getArea().

 Questo significa che qualsiasi classe che implementa Polygon deve fornire l'implementazione del metodo getArea().

Notare che la classe Rectangle (che implementa l'interfaccia Polygon) ha il metodo con implementazione getArea().

Perché utilizzare l'interfaccia?

Ora che sappiamo cosa è un'interfaccia, capiamo perché si utilizza l'interfaccia in Java.

  • Le interfacce forniscono specifiche che le classi (che le implementano) devono seguire.

  • Nell'esempio sopra, abbiamo utilizzato getArea() come specifica nell'interfaccia Polygon. Questo è come stabilire una regola, ossia dobbiamo essere in grado di ottenere l'area di ogni poligono. Pertanto, qualsiasi classe che implementa l'interfaccia Polygon deve fornire l'implementazione del metodo getArea().

  • Similmente agli abstract class, le interfacce ci aiutano a implementare l'astrazione in Java. Qui, sappiamo che getArea() calcola l'area del poligono, ma il modo di calcolare l'area è diverso per ogni poligono. Pertanto, le implementazioni di getArea() sono indipendenti.

  • Le interfacce sono anche utilizzate per implementare l'ereditarietà multipla in Java. Se un sottoclasse eredita da due o più classi, è una ereditarietà multipla.

    In Java, non è possibile realizzare l'ereditarietà multipla attraverso l'ereditarietà delle classi. Tuttavia, una classe può implementare più interfacce. Questo ci permette di ottenere la funzionalità dell'ereditarietà multipla in Java. Ad esempio,

    interfaccia Line {
       ...
    {}
    interface Polygon {
       ...
    {}
    class Rectangle implements Line, Polygon{
       ...
    {}

    In questo caso, Rectangle deve fornire l'implementazione di tutti i metodi di Line e Polygon.

Metodi privati e statici nell'interfaccia

In Java 8, le interfacce possono ora includere metodi statici.

Similmente ai classi, possiamo utilizzare il loro riferimento per accedere ai metodi statici dell'interfaccia. Ad esempio,

Polygon.staticMethod();

Inoltre, le interfacce sono supportate dai rilasci di Java 9. Ora, è possibile utilizzare all'interno delle interfaccemetodi privatieMetodi statici privati.

Poiché l'interfaccia non può essere istanziata, i metodi privati vengono utilizzati come metodi ausiliari per fornire supporto ai metodi dell'interfaccia.

Metodi di default nell'interfaccia

In Java 8, all'interno dell'interfaccia sono stati introdotti i metodi con implementazione (metodi di default). Prima di allora, tutti i metodi erano metodi astratti in Java.

Per dichiarare un metodo di default all'interno di un'interfaccia, utilizziamo la parola chiave default. Ad esempio,

public default void getSides() {
   //Corpo di getSides()
{}

Perché usare i metodi predefiniti?

Lasciate che vi mostriamo un esempio per capire perché Java ha introdotto i metodi predefiniti.

Supponiamo che dobbiamo aggiungere un nuovo metodo all'interfaccia.

Possiamo facilmente aggiungere questo metodo all'interfaccia senza eseguire nulla. Ma questa non è ancora la fine della storia. Tutti gli oggetti che implementano questa interfaccia devono fornire l'implementazione di questo metodo.

Se molti oggetti stanno implementando questo'interfaccia, dobbiamo tracciare tutti questi oggetti e modificarli. Questo è non solo fastidioso, ma anche soggetto a errori.

Per risolvere questo problema, Java ha introdotto i metodi predefiniti. I metodi predefiniti ereditano come i metodi normali.

Lasciate che vi mostriamo un esempio per capire meglio i metodi predefiniti.

Esempio 2: Metodi predefiniti

interface Polygon {
   void getArea();
   default void getSides() {
      System.out.println("Posso ottenere i lati del poligono.");
   {}
{}
class Rectangle implements Polygon {
   public void getArea() {
      int length = 6;
      int breadth = 5;
      int area = length * breadth;
      System.out.println("L'area del rettangolo è " + area);
   {}
   public void getSides() {
      System.out.println("Ho quattro lati.");
   {}
{}
class Square implements Polygon {
   public void getArea() {
      int length = 5;
      int area = length * length;
      System.out.println("L'area del quadrato è " + area);
   {}
{}
class Main {
   public static void main(String[] args) {
      Rectangle r1 = new Rectangle();
      r1.getArea();
      r1.getSides();
      Square s1 = new Square();
      s1.getArea();
   {}
{}

Risultato di output

L'area del rettangolo è 30
Ho quattro lati.
L'area del quadrato è 25

Nell'esempio sopra, abbiamo creato un'interfaccia Polygon. Polygon ha un metodo predefinito getSides() e un metodo astratto getArea().

Poi, la classe Rectangle implementa Polygon, Rectangle fornisce l'implementazione del metodo astratto getArea() e sovrascrive il metodo predefinito getSides().

Abbiamo creato un'altra classe Square, che implemente anche Polygon. In questo caso, Square fornisce solo l'implementazione del metodo astratto getArea().

Esempio di applicazione reale dell'interfaccia

Vediamo un esempio di interfaccia Java più pratico.

//Uso della funzione sqrt
import java.lang.Math;
interface Polygon {
   void getArea();
  
     //Calcolo del perimetro del poligono
   default void getPerimeter(int... sides) {
      int perimeter = 0;
      for (int side : sides) {
         perimeter += side;
      {}
   System.out.println("Perimetro: " + perimeter);
   {}
{}
class Triangle implements Polygon {
   private int a, b, c;
   private double s, area;
    //Inizializzazione dei lati del triangolo
   Triangle(int a, int b, int c) {
      this.a = a;
      this.b = b;
      this.c = c;
      s = 0;
   {}
    //Calcolo dell'area del triangolo
   public void getArea() {
      s = (double) (a + b + c) / 2;
      area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
      System.out.println("Area: " + area);
   {}
{}
class Main {
   public static void main(String[] args) {
      Triangle t1 = new Triangle(2, 3, 4);
      //Chiamata al metodo della classe Triangle
      t1.getArea();
      //Chiamata al metodo della classe Polygon
      t1.getPerimeter(2, 3, 4);
   {}
{}

Risultato di output

Area: 2.9047375096555625
Perimetro: 9

Nel programma sopra, abbiamo creato un'interfaccia Polygon. Questa include il metodo di default getParameter() e il metodo astratto getArea().

Possiamo calcolare la perimetro di tutti i poligoni allo stesso modo, quindi abbiamo implementato il corpo di getPerimeter() nella classe Polygon. Pertanto, tutti i poligoni che implementano Polygon possono utilizzare getPerimeter() per calcolare il perimetro.

Ma il modo di calcolare l'area è diverso per ogni poligono, perché le regole di calcolo dell'area sono diverse per ogni poligono.

Quindi, non c'è implementazione in Polygon ma include getArea(). E qualsiasi classe che implementa l'interfaccia Polygon deve fornire un'implementazione di getArea().

Interfaccia e parola chiave extends

Similmente a una classe, un'interfaccia può ereditare altre interfaccia, la parola chiave extends viene utilizzata per l'ereditarietà dell'interfaccia. Ad esempio:

interfaccia Line {
   //Membri dell'interfaccia Line
{}
interfaccia Polygon estende Line {
   //Membri dell'interfaccia Polygon e Line
{}

Nell'esempio sopra, l'interfaccia Polygon estende l'interfaccia Line. Ora, se una classe implementa Polygon, allora deve fornire un'implementazione per tutti i metodi astratti di Line e Polygon.

Attenzione, un'interfaccia può ereditare più interfaccia, simile a una classe che implementa più interfaccia. Ad esempio:

interfaccia A {
   ...
{}
interfaccia B {
   ... 
{}
Interfaccia C estende A, B {
   ...
{}