Salta al contenuto principale

Interfacce e classi astratte

Profile picture for user luca77king

Le interfacce e le classi astratte sono costrutti di programmazione che ci permettono di definire delle regole comuni per le classi che le implementano o le estendono. In altre parole, ci permettono di definire un set di metodi e proprietà che le classi dovranno avere, ma senza fornirne un'implementazione concreta.

Una classe astratta è una classe che non può essere istanziata direttamente, ma può essere usata solo come base per altre classi. Una classe astratta può avere metodi astratti, che sono metodi che non hanno un'implementazione concreta. Questi metodi vengono dichiarati con la keyword abstract e devono essere implementati dalle classi che estendono la classe astratta. Le classi astratte possono anche avere metodi concreti, ovvero metodi che hanno un'implementazione definita. Le classi astratte sono utilizzate per definire una classe base comune per un insieme di classi che condividono delle proprietà o dei comportamenti.

Un'interfaccia, invece, è un elenco di metodi e proprietà che una classe deve implementare. Le interfacce sono simili alle classi astratte, ma non hanno metodi concreti e non possono avere proprietà. Gli elementi delle interfacce vengono dichiarati con la keyword interface. Le interfacce sono utilizzate per definire un insieme di metodi che le classi devono implementare, ma non specificano come i metodi debbano essere implementati.

Differenze tra le interfacce e le classi astratte

La principale differenza tra le interfacce e le classi astratte è che le interfacce non possono avere metodi concreti o proprietà, mentre le classi astratte possono averli. Un'altra differenza importante è che una classe può estendere solo una classe astratta, ma può implementare molte interfacce.

Un'altra differenza è che i metodi delle interfacce devono essere implementati dalle classi che le implementano, mentre i metodi astratti delle classi astratte devono essere implementati dalle classi che le estendono. In altre parole, le classi che implementano un'interfaccia devono fornire un'implementazione concreta di tutti i metodi dell'interfaccia, mentre le classi che estendono una classe astratta devono fornire un'implementazione concreta solo per i metodi astratti.

A cosa servono le interfacce e le classi astratte

Le interfacce e le classi astratte servono a definire un'interfaccia comune per un insieme di classi che condividono delle proprietà o dei comportamenti. In altre parole, ci permettono di definire un set di regole comuni per le classi che le implementano o le estendono. Questo ci permette di scrivere del codice più flessibile e modulare, in quanto possiamo utilizzare le interfacce e le classi astratte per garantire che le classi rispettino un certo insieme di regole o comportamenti senza dover conoscere i dettagli di ogni classe specifica.

Le interfacce sono particolarmente utili quando abbiamo un insieme di classi che svolgono una stessa funzione ma con implementazioni diverse. Per esempio, possiamo definire un'interfaccia "Database" che definisce un insieme di metodi per la connessione e l'interazione con un database, e poi definire diverse classi che implementano questa interfaccia per lavorare con database diversi come MySQL, PostgreSQL o MongoDB. In questo modo, possiamo scrivere del codice che lavora con l'interfaccia "Database" e non dobbiamo preoccuparci di come i diversi tipi di database vengono implementati.

Le classi astratte, invece, sono utili quando abbiamo un insieme di classi che condividono molte proprietà o comportamenti, ma che hanno anche delle differenze specifiche. Possiamo definire una classe astratta "Animale" che definisce un insieme di proprietà e metodi comuni a tutti gli animali, come il nome, l'età e il verso. Poi possiamo definire diverse classi che estendono questa classe astratta per rappresentare diversi tipi di animali come "Cane", "Gatto" o "Uccello". In questo modo, possiamo scrivere del codice che lavora con la classe astratta "Animale" e utilizzare le proprietà e i metodi comuni a tutti gli animali, senza dover conoscere i dettagli specifici di ogni classe.

Definire un'interfaccia

Per definire un'interfaccia in PHP, si utilizza la parola chiave interface, seguita dal nome dell'interfaccia e dalle parentesi graffe che racchiudono la definizione dei metodi pubblici che l'interfaccia richiede alle classi che la implementano. Ecco un esempio di definizione di un'interfaccia:

interface Pagamento {
  public function paga($importo);
}

In questo esempio, l'interfaccia Pagamento richiede alle classi che la implementano di definire un metodo pubblico paga che accetta un parametro $importo.

Implementazione di un'interfaccia

Per implementare un'interfaccia in una classe, si utilizza la parola chiave implements seguita dal nome dell'interfaccia. La classe deve fornire un'implementazione concreta di tutti i metodi definiti nell'interfaccia.

Ecco un esempio di implementazione di un'interfaccia:

class PagamentoCarta implements Pagamento {
  public function paga($importo) {
    // Implementazione del metodo paga per il pagamento con carta di credito
  }
}

In questo esempio, la classe PagamentoCarta implementa l'interfaccia Pagamento fornendo un'implementazione concreta del metodo paga.

Estensione di un'interfaccia

Le interfacce possono anche estendere altre interfacce utilizzando la parola chiave extends. In questo modo, è possibile definire interfacce più specifiche che richiedono metodi supplementari rispetto a quelle che estendono.

Ecco un esempio di estensione di un'interfaccia:

interface Loggable {
  public function log($messaggio);
}

interface DatabaseLoggable extends Loggable {
  public function salvaLog();
}

In questo esempio, l'interfaccia DatabaseLoggable estende l'interfaccia Loggable, aggiungendo il metodo salvaLog che deve essere fornito dalle classi che la implementano.

Definizione di una classe astratta

Per definire una classe astratta in PHP, si utilizza la parola chiave abstract, seguita dalla parola chiave class e dal nome della classe astratta. La classe può definire sia proprietà che metodi, ma almeno uno dei metodi deve essere dichiarato come astratto, ovvero senza implementazione concreta. Ecco un esempio di definizione di una classe astratta:

abstract class Veicolo {
    protected $marca;

    public function getMarca() {
        return $this->marca;
    }

    abstract public function avvia();
}

In questo esempio, la classe astratta Veicolo definisce la proprietà $marca e i metodi getMarca() e avvia(), ma il secondo è dichiarato come astratto.

Implementazione di una classe astratta

Per implementare una classe astratta in una classe concreta, si utilizza la parola chiave extends. La classe concreta deve fornire un'implementazione concreta di tutti i metodi astratti dichiarati nella classe astratta. Ecco un esempio di implementazione di una classe astratta:

class Auto extends Veicolo {
    public function avvia() {
        // Implementazione del metodo avvia per l'auto
    }
}

In questo esempio, la classe Auto estende la classe astratta Veicolo e fornisce un'implementazione concreta del metodo avvia().

Metodi concreti e metodi astratti in una classe astratta

Una classe astratta può definire sia metodi concreti che metodi astratti. I metodi concreti forniscono un'implementazione predefinita che può essere utilizzata dalle classi che estendono la classe astratta. I metodi astratti, d'altra parte, devono essere implementati dalle classi che estendono la classe astratta.

Ecco un esempio di classe astratta con metodi concreti e metodi astratti:

class Auto extends Veicolo {
    public function avvia() {
        // Implementazione del metodo avvia per l'auto
    }
}

In questo esempio, la classe astratta Forma definisce il metodo setColore() come concreto e il metodo area() come astratto.

Le classi astratte sono un utile strumento per fornire una base comune di proprietà e metodi per diverse classi che condividono una certa funzionalità. Possono essere estese per fornire funzionalità più specifiche e personalizzate dalle classi che le utilizzano.