Come organizzare il codice orientato agli oggetti con l’ereditarietà
È comune riutilizzare il codice nella programmazione orientata agli oggetti. Esistono classi in modo da poter creare oggetti senza dover scrivere le stesse variabili e funzioni più e più volte.
Ma per quanto riguarda le classi stesse? A volte anche le classi sono molto simili. Ad esempio, un albero ha rami, radici e un tronco. Questo vale per Elms, Oaks e Ponderosa Pines.
Se stavi aggiungendo un albero a un gioco, potresti creare parti di alberi per dozzine di alberi. Ma sarebbe più facile creare una classe albero e fare in modo che ogni altro albero erediti le sue proprietà.
Perché l'ereditarietà è importante?
C'è un concetto nella programmazione orientata agli oggetti chiamato "keep it DRY". DRY sta per "Don't Repeat Yourself". Se ti ritrovi a copiare e incollare molto codice, stai anche introducendo spazio per molti errori.
Supponiamo che tu stia scrivendo il codice per un nuovo gioco Tamagotchi. Il primo animale domestico virtuale sarà un orso polare. Quindi crei una classe chiamata PolarBear in JavaScript / TypeScript.
class PolarBear {
private _weight: number = 990;
constructor(weight: number = 0) {
this._weight = weight
}
makeNoise() {
console.log("made a roar");
}
eat() {
console.log("eats whatever it wants");
}
sleep() {
console.log("got a good night's sleep");
}
roam() {
console.log("wandered about aimlessly");
}
}
Poi il tuo capo ti dice che la dirigenza superiore ha avuto un enorme passo avanti. Si sono resi conto che non siamo più negli anni '90 e possono contenere più di 5K di memoria nel Tamagotchi. E ora vogliono tutti gli orsi.
Ti rimbocchi le maniche e torni al lavoro, creando copie della classe dell'orso. Poi il tuo capo bussa di nuovo alla tua porta. Si scopre che vogliono che il gioco sia più educativo. Ora devi aggiungere le informazioni sull'origine a ciascun animale domestico.
Non stai più duplicando il codice. Ora stai cambiando centinaia di righe di codice per tutte le otto specie di orso. Ecco come avvengono gli errori e vengono introdotti i bug.
Mentre stai macinando via, il tuo capo si avvicina di nuovo. Ora la dirigenza superiore vuole anche tutti i roditori nel gioco. Oh, e una giraffa.
Sai che quando hai finito, vorranno scimmie o anche qualcos'altro. Deve esserci un modo migliore.
Invece di creare Tamogatchi di nuova generazione, potresti sempre giocare con quelli esistenti .
Eredità al salvataggio

Per domare il tuo serraglio virtuale, dovrai organizzarti. L'ereditarietà ti aiuta a organizzare le tue classi aggiungendovi relazioni genitore e figlio.
Orsi neri, grizzly e bradipi sono tutti orsi. Orsi, roditori e scimmie sono tutti animali. Ed è così che struttureremo il nostro albero genealogico.

Questo è l'aspetto di una parte del codice:
class Animal {
private _weight: number;
private _origin: string;
constructor(weight: number = 0, origin: string = "") {
this._weight = weight;
this._origin = origin;
}
makeNoise(noise: string = "") {
console.log("made a noise that sounded like: " + noise);
}
eat(food: string = "") {
console.log("eats " + food);
}
sleep() {
console.log("got a good night's sleep");
}
roam() {
console.log("wandered about aimlessly");
}
}
class Bear extends Animal {
constructor(weight: number, origin: string) {
super(weight, origin);
}
makeNoise(noise: string = "roar") {
super.makeNoise(noise);
}
eat(food: string = "whatever it wants") {
super.eat(food);
}
}
class GrizzlyBear extends Bear {
constructor(weight: number = 600, origin: string = "North America") {
super(weight, origin);
}
}
class Panda extends Bear {
constructor(weight: number = 230, origin: string = "China") {
super(weight, origin);
}
makeNoise() {
super.makeNoise("squeek");
}
eat() {
super.eat("shoots and leaves");
}
}
Puoi giocare con il codice nella sandbox TypeScript .
Questo è stato un grande esempio, ma il codice è abbastanza semplice e tutte le classi discendono dalla classe Animal . Puoi vedere che Bear estende Animal . E GrizzlyBear e Panda estendono la classe Orso . La classe Bear crea suoni predefiniti e funzioni eat . La classe GrizzlyBear utilizza queste funzioni predefinite, ma Panda no.
In altre parole, la classe GrizzlyBear non sovrascrive le funzioni Bear . Poiché GrizzlyBear estende Bear , utilizzerà automaticamente le funzioni definite da Bear . Ma poiché Panda sovrascrive le funzioni makeNoise e eat , le utilizzerà invece.
Trovare relazioni con la tecnica "is-a, has-a"
Per capire se una classe dovrebbe davvero estendere un'altra classe, puoi chiederti se esiste una relazione "è-uno" o "ha-un" tra di loro.
- Un lemure "è-una" scimmia.
- Un canguro "è-un" marsupiale.
- La zampa di un coniglio, però, non è un coniglio. Un coniglio "ha un piede".
Questo esempio è un po 'semplicistico, ma quando si ha a che fare con lezioni del mondo reale, può essere molto utile.
Pratica e comprensione pratiche sull'ereditarietà

Pronto ad applicare ciò che hai imparato?
- Visita la sandbox e inserisci il resto delle classi di animali dell'esempio sopra.
- Aggiungi una lezione di scimmia .
- Aggiungi una classe ProboscisMonkey che estende la tua classe scimmia.
L'ereditarietà è più di un semplice codice ben organizzato. È una parte fondamentale della programmazione orientata agli oggetti. L'ereditarietà aiuta a semplificare la comunicazione tra gli oggetti. E consente una progettazione orientata agli oggetti più avanzata, come con il polimorfismo. Puoi saperne di più sull'ereditarietà dalla documentazione di TypeScript .

