"Ciao, Amigo! Ora ecco un argomento che penso userai molto. Sto parlando di eredità. "

Per chi non lo sapesse, la programmazione è come per magia. Quindi vorrei iniziare con un'analogia...

Supponi di essere un mago che vuole creare un cavallo volante. Potresti provare a evocare un Pegaso. Ma dal momento che i cavalli volanti non sono presenti in natura, avrai un momento davvero difficile. Avresti molto lavoro da fare. Sarebbe molto più facile iniziare con un cavallo ed evocare alcune ali.

Eredità.  Vantaggi dell'eredità - 1

In programmazione, chiamiamo questo processo «eredità» . Supponiamo di dover scrivere una classe molto complessa. Potresti dedicare molto tempo a scrivere codice da zero e quindi eseguire lunghi test per trovare bug. Ma perché farlo nel modo più duro? È meglio guardarsi intorno e vedere se la classe che stai cercando esiste già?

Diciamo che trovi una classe che implementa l'80% delle funzionalità di cui hai bisogno. Puoi semplicemente copiare il suo codice nella tua classe. Ma questo avrebbe diversi inconvenienti:

1) La classe che trovi potrebbe essere già compilata in bytecode. Potresti non avere accesso al suo codice sorgente.

2) Potresti avere il codice sorgente per la classe, ma anche lavorare in un'azienda che potrebbe essere citata in giudizio per un paio di miliardi se usi anche 6 righe del codice di qualcun altro. E poi ti faranno causa.

3) Ciò porta alla duplicazione non necessaria di lotti di codice. E se l'autore dell'altra classe trova un bug e lo corregge, hai ancora il bug.

Esiste una soluzione più elegante che non richiede l'ottenimento di autorizzazioni legali per il codice della classe originale. In Java, puoi semplicemente dichiarare l'altra classe come genitore della tua classe. Ciò equivale ad aggiungere il codice di quella classe alla tua classe. Tutti i dati e i metodi della classe genitore appariranno nella tua classe. Ad esempio, potresti ereditare da un «cavallo», aggiungere «ali» e ottenere un «Pegaso».

Eredità.  Vantaggi dell'eredità - 2

"Molto interessante. Per favore, continua."

"L'ereditarietà ha anche altri usi. Supponi di avere dieci classi molto simili. Hanno dati e metodi corrispondenti. Potresti creare una classe base speciale , spostare i dati (e i metodi associati) nella classe base e avere quelle dieci classi ereditare da esso. In altre parole, per ogni classe, si indica che ha una classe genitore, nota anche come classe base."

"Proprio come i vantaggi dell'astrazione si rivelano veramente solo in connessione con l'incapsulamento, i vantaggi dell'ereditarietà sono amplificati dal polimorfismo. Ma te ne parlerò domani. Oggi diamo un'occhiata ad alcuni esempi di ereditarietà."

"Supponiamo che stiamo scrivendo un programma di scacchi. Avremo bisogno di lezioni per i pezzi degli scacchi. Quali classi suggeriresti, Amigo?"

"Re, Regina, Alfiere, Cavaliere, Torre e Pedone".

"Molto bene. Non ti sei perso niente."

"E quali dati suggeriresti di memorizzare in queste classi?"

"La posizione sulla scacchiera (x e y) e il valore di ogni pezzo. Dopo tutto, alcuni pezzi sono più preziosi di altri."

"E quali sono le differenze tra queste classi?"

"Differiscono nel modo in cui muovono i pezzi. Nel loro comportamento."

"Sì. Potresti definirli come classi come questa:"

class King
{
int x;
int y;
int worth;
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen
{
int x;
int y;
int worth;
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook
{
int x;
int y;
int worth;
void rookMove()
{
//code that defines,
//how the rook moves
}
}
class Knight
{
int x;
int y;
int worth;
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop
{
int x;
int y;
int worth;
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn
{
int x;
int y;
int worth;
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

"Sì, è proprio così che lo scriverei."

"Ma guarda come potresti usare l'ereditarietà per scrivere meno codice. Possiamo spostare metodi e dati identici in una classe comune. Chiamiamola ChessItem. Non ha senso creare oggetti ChessItem, dal momento che non corrispondono a nessuno pezzo degli scacchi. Ma la classe sarebbe estremamente utile:"

class King extends ChessItem
{
void kingMove()
{
//code that defines,
//how the king moves
}
}
class Queen extends ChessItem
{
void queenMove()
{
//code that defines,
//how the queen moves
}
}
class Rook extends ChessItem
{
void rookMove()
{
//code that defines,
//how the rook moves
}
}
 class ChessItem
{
int x;
int y;
int worth;
}
 
class Knight extends ChessItem
{
void knightMove()
{
//code that defines,
//how the knight moves
}
}
class Bishop extends ChessItem
{
void bishopMove()
{
//code that defines,
//how the bishop moves
}
}
class Pawn extends ChessItem
{
void pawnMove()
{
//code that defines,
//how the pawn moves
}
}

"Interessante!"

"Assolutamente! Il vantaggio è particolarmente grande nei progetti contenenti migliaia di oggetti diversi e centinaia di classi. In questo caso, le classi scelte correttamente possono non solo semplificare notevolmente la logica, ma anche ridurre il codice richiesto di un fattore dieci."

"Allora cosa devi fare per ereditare una classe?"

"Dopo aver dichiarato una classe, usiamo la parola chiave ' extends ', seguita dal nome della classe genitore. Puoi ereditare solo da una classe. "

Eredità.  Vantaggi dell'eredità - 3

L'immagine mostra una "mucca" che ha ereditato da un «maiale». Il «Maiale» eredita dal «pollo», e il «pollo» eredita dall'«uovo». Ogni classe ha un solo genitore! Tale eredità non è sempre logica. Se hai solo un maiale, ma hai davvero bisogno di una mucca, i programmatori spesso non possono resistere al desiderio di trasformare il "maiale" in una "mucca".

"Ma cosa succede se voglio ereditare da due classi? C'è qualcosa che posso fare?!"

"Non proprio. Le classi Java non supportano l'ereditarietà multipla dell'implementazione: una classe può avere solo una singola classe genitore. Ma esiste l'ereditarietà multipla del tipo, il che significa che una classe può implementare più di un'interfaccia. Questo mitiga leggermente il problema. "

"Capisco. E cos'è un'interfaccia?"

"Ti parlerò delle interfacce domani. Per ora, continuiamo ad approfondire l'ereditarietà."