1. Classe base comune

Oggi ci godremo un buffet di argomenti interessanti. Ricordi quando abbiamo introdotto la ChessItemclasse base per semplificare tutte le classi che rappresentano i pezzi degli scacchi? Lo spero 🙂

Ora immagina che ogni pezzo abbia un draw()metodo che lo gestisca disegnandolo sullo schermo. Chiami il draw()metodo e il pezzo si disegna alle sue coordinate correnti. Sarebbe conveniente spostare questo metodo nella classe base.

Se il draw()metodo fosse nella classe base ChessItem, potremmo sovrascriverlo nelle classi pezzo e scrivere un codice elegante come questo:

class ChessBoard
{
   public void drawAllChessItems()
   {
      // Add the pieces to the list
      ArrayList<ChessItem> items = new ArrayList<ChessItem>();
      items.add(new King());
      items.add(new Queen());
      items.add(new Bishop());

      // Draw them regardless of their type
      for(ChessItem item: items)
      {
         item.draw();
      }
   }
}

Introducendo la ChessItemclasse base, siamo riusciti a semplificare notevolmente il codice: non è necessario chiamare separatamente i metodi di ogni classe, possiamo facilmente memorizzare tutti gli oggetti in un'unica raccolta, ecc.

Ma ecco una domanda interessante: cosa dovrebbe disegnare sullo schermo il draw()metodo dichiarato direttamente nella ChessItemclasse? Dopotutto, non esiste un pezzo del genere negli scacchi, quindi non c'è niente da disegnare.

Esatto. Inoltre, non ha senso creare ChessItemoggetti direttamente. Non è un pezzo degli scacchi, ma solo un'astrazione , una classe che abbiamo creato per nostra comodità. Ecco come funziona l'astrazione in OOP : spostiamo dati e metodi importanti (quelli condivisi da tutti i pezzi) in una classe base e manteniamo le loro differenze in classi discendenti separate.


2. Classi astratte

Classi astratte

Per tali situazioni, Java ha un tipo speciale di classe: la classe astratta . Sono progettati per rendere più facile per i programmatori lavorare con classi simili e ridurre la quantità di codice duplicato in esse.

Ecco tre cose da sapere sulle classi astratte.

Metodo senza implementazione

Una classe astratta può avere una dichiarazione di metodo senza un'implementazione. Questo è esattamente ciò che rende il metodo astratto. Il corpo del metodo viene semplicemente sostituito con un punto e virgola. E prima del nome del metodo, scriviamo la abstractparola chiave. Esempio:

public abstract class ChessItem
{
   public int x, y; // Coordinates
   private int value; // The piece's value
   public int getValue() // Ordinary method that returns value field
   {
      return value;
   }

   public abstract void draw(); // Abstract method. The implementation is missing.
}

Classe astratta

Ogni metodo senza implementazione è contrassegnato con la parola chiave abstract. Se una classe ha anche un solo metodo astratto, anche la classe viene contrassegnata con la abstractparola chiave.

Proibire la creazione di oggetti

Non è possibile creare oggetti di una classe astratta . Tale codice semplicemente non verrà compilato.

Codice Descrizione
ChessItem item = new ChessItem();
item.draw();
Questo codice non compila :
ChessItem item = new Queen();
item.draw();
Ma puoi farlo

Ereditare una classe astratta

Se la tua classe eredita una classe astratta, allora devi sovrascrivere tutti i metodi astratti ereditati, cioè devi scrivere un'implementazione per loro. Altrimenti, anche la tua stessa classe dovrà essere dichiarata astratta.

Se una classe ha anche un solo metodo non implementato dichiarato direttamente in essa o ereditato da una classe genitore, allora la classe è considerata astratta.

E perché è necessario tutto questo? Perché sono necessarie le classi astratte? Non è possibile utilizzare invece quelli ordinari? E invece di metodi astratti, non potremmo semplicemente scrivere due parentesi graffe vuote come corpo del metodo?

Potremmo. Ma queste restrizioni sono simili al privatemodificatore. Usiamo la parola chiave private per impedire deliberatamente ad altri programmatori di accedere direttamente ai dati e per costringerli a utilizzare solo i nostri metodi pubblici quando scrivono le loro classi.

È lo stesso con le classi astratte. L'autore di una classe astratta non desidera che gli oggetti della classe vengano creati. Invece, l'autore si aspetta che i metodi astratti vengano ereditati dalla classe astratta e quindi sovrascritti.

Il vantaggio di questo approccio è subito evidente nei grandi progetti. Più classi hai, più chiaramente devi delineare i loro ruoli. Vedrai i vantaggi di questo approccio nel prossimo futuro. Ogni cosa passa attraverso questo.