"Ciao, Amigo! Abbiamo un nuovo affascinante argomento."

"Oggi è solo un giorno di argomenti affascinanti!"

"Perché grazie!"

"Prego."

"Ricordi quando abbiamo introdotto la classe base ChessItem per semplificare tutte le classi per i pezzi degli scacchi?"

"SÌ."

"Ora immagina che ogni pezzo abbia un metodo che gestisce il rendering del pezzo sullo schermo. Tu chiami il metodo e il pezzo disegna se stesso alle sue coordinate correnti. Sarebbe utile spostare questo metodo nella classe base?"

"SÌ." Dopo aver appreso del polimorfismo, sarei in grado di chiamare il metodo render per tutti i pezzi, indipendentemente dal loro tipo. Qualcosa come questo:"

Per esempio:
class ChessBoard
{
  public void drawAllChessItems()
  {
  //draw them regardless of their type.
  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();
  }
 }
}

"Ben fatto. Esattamente. E cosa farebbe il metodo draw della stessa classe ChessItem?"

"Non lo so. Gli scacchi non hanno un pezzo del genere. E questo significa che non hanno una rappresentazione visiva."

"Precisamente. E non ha senso creare un oggetto ChessItem. Non esiste un pezzo degli scacchi del genere. È solo un'astrazione , una classe che abbiamo creato per comodità. Ecco come funziona l'astrazione in OOP: abbiamo spostato tutte le parti importanti (condivise da tutti i pezzi) dati e metodi in una classe base , ma abbiamo mantenuto le loro differenze nelle classi corrispondenti a specifici pezzi degli scacchi."

Java ha un tipo di classe speciale per questo: la classe astratta . Ecco tre cose da ricordare sulle classi astratte.

1) Una classe astratta può dichiarare metodi senza implementarli. Tale metodo è chiamato metodo astratto.

Per esempio:
 public abstract class ChessItem
{
 public int x, y; //coordinates
 private int value; //the piece's "value"

 public int getValue() //an ordinary method, returns value
 {
   return value;
 }

 public abstract void draw(); //abstract method. There is no implementation.

}

2) Un metodo astratto è contrassegnato con la parola chiave abstract .

Se una classe ha anche un solo metodo astratto, anche la classe è contrassegnata con abstract .

3) Non è possibile creare oggetti di una classe astratta. Il codice che tenta di farlo semplicemente non verrà compilato.

codice java Descrizione
ChessItem item = new ChessItem();
item.draw();
Questo codice non verrà compilato.
ChessItem item = new Queen();
item.draw();
Ma puoi farlo.

4) Se la tua classe eredita una classe astratta, devi sovrascrivere tutti i metodi astratti ereditati, cioè devi implementarli. In caso contrario, anche la tua classe dovrà essere dichiarata abstract. Se la classe ha anche un solo metodo non implementato dichiarato direttamente nella classe o ereditato dalla classe genitore, allora la classe è considerata astratta.

"Ma perché tutto questo è necessario? Perché abbiamo bisogno di classi astratte? Non è possibile utilizzare invece classi ordinarie? E invece di metodi astratti, non possiamo semplicemente creare implementazioni vuote costituite da parentesi graffe aperte e chiuse?"

"Potresti. Ma queste restrizioni sono come il privatemodificatore. Usiamo il privatemodificatore per bloccare deliberatamente l'accesso diretto ai dati, in modo che altri programmatori e le loro classi utilizzino i nostri publicmetodi."

Lo stesso vale per una classe astratta. Chiunque abbia scritto la classe non vuole che nessuno crei istanze della classe. Al contrario, l'autore si aspetta che i metodi astratti della sua classe astratta vengano ereditati e sovrascritti.

"Continuo a non capire perché vorremmo complicarci la vita in questo modo".

"Il vantaggio di questa funzione è evidente nei progetti di grandi dimensioni. Più classi hai, più chiaramente devi delineare i loro ruoli. Vedrai il vantaggio di farlo, e presto. Tutti devono affrontarlo."