Classe astratta vs. Interfaccia in Java: spiegazione con esempi

Le classi e le interfacce astratte vengono utilizzate per l’astrazione in Java. L’astrazione nella programmazione orientata agli oggetti si riferisce al nascondere i dettagli di implementazione agli utenti finali.

In astratto, puoi sapere quali sono le funzionalità, ma non puoi sapere come sono state implementate.

Diamo un’occhiata a ciascuno di essi e cerchiamo di capire perché vengono utilizzati.

Classe astratta

Una classe che non può essere istanziata come oggetto e che può contenere o meno metodi astratti è definita classe astratta in Java. Un metodo astratto è un metodo che non ha un corpo di implementazione quando dichiarato.

Esempio di una classe astratta GraphicObject – Oracle

È possibile creare una classe astratta specificando la parola chiave abstract prima della parola chiave class.

abstract class abstractClass {
    void run() {
        System.out.println("ran");
    }
}

Una classe astratta può essere estesa da altre classi. In altre parole, può anche essere sottoclasse.

abstract class AbstractClass {
    void run() {
        System.out.println("ran");
    }
}

class ExtendingAbstractClass extends AbstractClass {
    void newMethod() {
        System.out.println("new");
    }

    @Override
    void run() {
        System.out.println("override");
    }
}

Le classi astratte vengono utilizzate per implementare metodi comuni tra più classi che estendono una determinata classe astratta. Inoltre, la possibilità di definire metodi astratti all’interno di classi astratte li rende incredibilmente utili per classi che hanno metodi simili ma con implementazioni diverse. Facciamo un esempio.

Considera un’auto che ha alcune funzionalità, come avvio, arresto, retromarcia, ecc. Queste funzionalità sono comuni a tutti i tipi di auto.

Ma per quanto riguarda le funzionalità di automazione come la guida autonoma? L’implementazione di tali funzionalità può differire per i diversi tipi di auto. Vediamo come è possibile creare un programma orientato agli oggetti ad esso correlato.

Prima di tutto, crea una classe Car che verrà estesa da più classi di diversi tipi di auto.

abstract class Car {
    void start() {
        // implementation
        System.out.println("runs car");
    }

    void stop() {
        // implementation
        System.out.println("engine stops");
    }

    void reverse() {
        // implementation
        System.out.println("reverse mode enabled");
    }

    abstract void selfDrive();
}

I metodi start(), stop() e reverse() sono metodi comuni a tutte le auto. Quindi la loro implementazione è già definita all’interno della classe Car stessa. Tuttavia, un certo tipo di auto può avere diverse implementazioni della modalità di guida autonoma. E quindi, puoi definire selfDrive() come un metodo astratto e implementarlo in modi diversi in diverse classi di diversi tipi di auto.

class CarTypeA extends Car {
    @Override
    void start() {
        super.start();
    }

    @Override
    void stop() {
        super.stop();
    }

    @Override
    void reverse() {
        super.reverse();
    }

    void selfDrive() {
        // custom implementation
        System.out.println("Type A self driving mode enabled");
    }
}
class CarTypeB extends Car {
    // ...all similar methods

    void selfDrive() {
        // custom implementation
        // different implementation than CarTypeB
        System.out.println("Type B self driving mode enabled");
    }
}

È importante notare che, se una sottoclasse non implementa tutti i metodi astratti definiti nella classe astratta, allora dovrebbe essere dichiarata come una classe astratta stessa.

Interfaccia

Un’interfaccia è un modo per dire a una classe quali metodi devono essere implementati da essa. Ad esempio, se consideri l’esempio di un’auto, ha alcune funzioni di base. Può iniziare, muoversi e fermarsi. Queste funzioni sono comuni a tutte le auto.

Quindi, se implementi un’interfaccia di un’auto in una classe, devi implementare tutti i metodi affinché l’auto funzioni correttamente e in sicurezza.

Analogamente alle classi astratte, non possiamo istanziare o creare oggetti di un’interfaccia. Può essere considerata una classe completamente astratta perché contiene solo metodi astratti, cioè metodi senza un corpo di implementazione.

È possibile creare un’interfaccia utilizzando la parola chiave interface.

interface CAR {
    void start();
    void stop();
    void move();
}

Implementa un’interfaccia usando la parola chiave implements quando definisci una classe.

class CarTypeB implements CAR {
    public void start() {
        System.out.println("started");
    }

    public void stop() {
        System.out.println("stopped");
    }

    public void move() {
        System.out.println("running");
    }
}

Somiglianza

Nessuna istanza come oggetto è l’unica cosa che le classi astratte e le interfacce hanno in comune.

Differenze

Interfaccia di classe astrattaEreditarietà e implementazioneSolo una classe astratta può essere ereditata da una classe.Interfacce multiple possono essere implementate da una classe.Tipi di variabiliPuò avere variabili finali, non finali, statiche e non statiche.Può avere solo variabili statiche e finali. Tipi di metodo Può contenere sia metodi astratti che non astratti. Può contenere solo metodi astratti, ma i metodi statici sono un’eccezione. Modificatori di accesso Una classe astratta può avere un modificatore di accesso. Le firme dei metodi definite nell’interfaccia sono pubbliche per impostazione predefinita. Un’interfaccia non ha un modificatore di accesso. Costruttori e distruttori Può dichiarare costruttori e distruttori. Non può dichiarare costruttori o distruttori. Velocità Veloce Lenta Differenze tra classe astratta e interfaccia

Quando utilizzare la classe astratta e l’interfaccia?

Usa le classi astratte quando:

  • Vuoi condividere alcuni metodi e campi comuni tra più classi.
  • Dichiarare campi non statici e non finali per modificare lo stato dell’oggetto a cui sono associati.

Puoi utilizzare le interfacce quando:

  • Vuoi definire il comportamento di una classe che implementa l’interfaccia, ma non ti interessa il modo in cui è implementata.
  • Vuoi assicurarti che una classe implementi tutti i metodi per funzionare correttamente.

Parole finali

Le interfacce vengono utilizzate principalmente per creare API perché possono fornire una struttura per implementare funzionalità senza preoccuparsi dell’effettiva implementazione.

Le classi astratte vengono generalmente utilizzate per condividere metodi astratti e non astratti comuni tra più classi, che estendono la classe astratta per rendere il codice più riutilizzabile.

Scopri di più su Java con l’aiuto di questi corsi online per Java. Ti stai preparando per un colloquio su Java? Ecco alcune domande dell’intervista sulla programmazione orientata agli oggetti.