back to top

Java: il modificatore abstract (e le classi astratte)

Il modificatore abstract rappresenta l’antitesi del modificatore final in Java. Il modificatore abstract può essere applicato sia a metodi che a classi, mentre non ha senso per le variabili. Vediamo come definire un metodo astratto, che richiede una sintassi specifica: si omettono le parentesi graffe. Un esempio di definizione di un metodo astratto è il seguente:

public abstract tipoDiRitorno nomeMetodo();

Come si può notare, un metodo astratto non contiene implementazioni e si limita a fornire una definizione.

Pubblicità

Quando dichiariamo un metodo astratto all’interno di una classe, anche la classe stessa deve essere definita come abstract. Una classe astratta non può essere istanziata, coerentemente con il concetto di oggetto, che è una realizzazione concreta di una classe. Pertanto, se non possiamo istanziare una classe astratta, non possiamo richiamare i suoi metodi astratti. Tuttavia, è possibile utilizzare l’override dei metodi nelle sottoclassi che estendono la classe astratta.

Ma a cosa servono queste classi astratte, considerando che non possono essere istanziate? Facciamo un esempio: immaginiamo di avere una classe Programmatore con un metodo astratto che definisce come un programmatore sviluppa una determinata applicazione. La definizione della classe potrebbe essere:

public abstract class Programmatore {
  public abstract void programma();
}

È necessario definire la classe Programmatore come astratta, poiché il metodo programma() è anch’esso astratto. Questo metodo modella l’approccio alla programmazione che un programmatore applica in base al linguaggio utilizzato. Ad esempio, un programmatore che utilizza C adotterà un approccio procedurale, mentre un programmatore Java avrà un approccio orientato agli oggetti; quindi il metodo programma() avrà significati diversi in base al contesto.

Nei dettagli, nelle sottoclassi ProgrammatoreC e ProgrammatoreJava, effettueremo l’override del metodo programma() per adattarlo ai diversi paradigmi di programmazione. La classe astratta, quindi, funge da modello generico e richiede che le sottoclassi implementino il comportamento specifico mediante l’override dei metodi astratti.

A questo punto, potrebbe sembrare che le classi astratte, usate come definizioni per gruppi di oggetti, non debbano includere un costruttore in quanto non possono essere istanziate. Questo è un fraintendimento: esiste il costruttore della superclasse, che viene richiamato automaticamente durante la creazione di un oggetto. Pertanto, quando istanziamo una classe derivata da una classe astratta, invochiamo sempre il costruttore di quest’ultima. Dunque, è possibile includere attributi e un costruttore all’interno di una classe astratta, e può essere utile definire attributi generali che verranno ereditati dalle classi derivate. Per esempio, la classe Programmatore potrebbe essere ridefinita nel seguente modo:

public abstract class Programmatore {

  private String nome;
  private String cognome;
  private int anniEsperienza;
    
  public Programmatore(String n, String c, int a){
    nome = n;
    cognome = c;
    anniEsperienza = a;
  }

  public abstract void programma();
}

Quando estendiamo la classe astratta creando, ad esempio, la classe ProgrammatoreJava, richiameremo il costruttore della superclasse utilizzando il riferimento super(), passando i valori per nome, cognome e anni di esperienza. In questo modo, ogni sottoclasse di Programmatore avrà accesso a questi attributi e potrà implementarli secondo le proprie esigenze.

Pubblicità
Articolo precedente
Articolo successivo