4.1 L'ereditarietà è semplice
L'ereditarietà è un concetto fondamentale della programmazione orientata agli oggetti (OOP) che consente a una classe (chiamata classe figlia o sottoclasse) di ereditare campi e metodi di un'altra classe (chiamata classe genitore o superclasse).
Questo approccio permette di creare classi più generali e riutilizzare il codice, migliorando l'organizzazione e la manutenibilità del codice.
Perché l'ereditarietà è importante?
Supponiamo che tu debba scrivere un po' di codice e decida di farlo sotto forma di classe. Poi scopri che nel tuo progetto esiste già una classe che fa quasi tutto ciò di cui hai bisogno nella tua classe. Puoi semplicemente copiare il codice di quella classe nella tua e usarla come meglio credi.
Oppure puoi "come copiare". Puoi dichiarare quella classe come genitore della tua classe, e allora JavaScript aggiungerà alla tua classe il comportamento della classe genitore.
Immagina di essere la natura e voler creare un Cane. Cosa sarà più veloce: creare un cane da un batterio in un miliardo di anni o addomesticare un lupo in 200 mila anni?
4.2 Concetto di ereditarietà tramite prototipi
L'ereditarietà tramite prototipi in JavaScript è uno dei meccanismi principali che consente agli oggetti di ereditare proprietà e metodi di altri oggetti. Questo permette di creare gerarchie di oggetti complesse e di riutilizzare il codice.
Ogni oggetto in JavaScript ha una proprietà nascosta [[Prototype]], che indica il suo prototipo. I prototipi sono usati per implementare l'ereditarietà, permettendo agli oggetti di ereditare proprietà e metodi da altri oggetti.
Esempio di semplice ereditarietà
Passo 1: Creazione dell'oggetto base
const animal = {
eat() {
console.log('Mangiare...');
},
sleep() {
console.log('Dormire...');
}
};
Passo 2: Creazione dell'oggetto erede
const dog = Object.create(animal);
dog.bark = function() {
console.log('Abbaiare...');
};
Passo 3: Uso delle proprietà e dei metodi ereditati
dog.eat(); // Visualizzerà: Mangiare...
dog.sleep(); // Visualizzerà: Dormire...
dog.bark(); // Visualizzerà: Abbaiare...
In questo esempio, l'oggetto dog
eredita i metodi eat()
e sleep()
dall'oggetto
animal
e aggiunge il proprio metodo — bark()
.
4.3 Ereditarietà profonda tramite prototipi
Catena di prototipi
In JavaScript, l'ereditarietà può diventare più complessa quando gli oggetti ereditano l'uno dall'altro, formando una catena di prototipi.
Esempio di catena di prototipi
In questo esempio, l'oggetto dog
eredita da mammal
, che a sua volta eredita da
animal
. Questo crea una catena di prototipi, dove dog
ha accesso a tutti i metodi
di mammal
e animal
.
const animal = {
eat() {
console.log('Mangiare...');
}
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Camminare...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Abbaiare...');
};
dog.eat(); // Visualizzerà: Mangiare...
dog.walk(); // Visualizzerà: Camminare...
dog.bark(); // Visualizzerà: Abbaiare...
Verifica della catena di prototipi
Il metodo isPrototypeOf()
permette di verificare se un oggetto è il prototipo di un altro oggetto.
Esempio:
console.log(animal.isPrototypeOf(mammal)); // Visualizzerà: true
console.log(mammal.isPrototypeOf(dog)); // Visualizzerà: true
console.log(animal.isPrototypeOf(dog)); // Visualizzerà: true
4.4 Sovrascrittura dei metodi
L'ereditarietà tramite prototipi consente non solo di aggiungere nuovi metodi, ma anche di sovrascrivere i metodi esistenti.
Esempio di sovrascrittura dei metodi
In questo esempio, il metodo speak()
dell'oggetto dog
sovrascrive il metodo speak()
dell'oggetto animal
:
const animal = {
speak() {
console.log('L'animale parla');
}
};
const dog = Object.create(animal);
dog.speak = function() {
console.log('Il cane abbaia');
};
animal.speak(); // Visualizzerà: L'animale parla
dog.speak(); // Visualizzerà: Il cane abbaia
Chiamata del metodo dell'oggetto genitore
Per chiamare il metodo dell'oggetto genitore in JavaScript, puoi usare il metodo call()
o apply()
.
Esempio:
const animal = {
speak() {
console.log('L'animale parla');
}
};
const dog = Object.create(animal);
dog.speak = function() {
animal.speak.call(this);
console.log('Il cane abbaia');
};
dog.speak();
// Visualizzerà:
// L'animale parla
// Il cane abbaia
4.5 Uso avanzato dell'ereditarietà tramite prototipi
Estensione degli oggetti incorporati
Puoi estendere gli oggetti incorporati di JavaScript aggiungendo metodi ai loro prototipi.
Esempio:
Array.prototype.sum = function() {
return this.reduce((acc, value) => acc + value, 0);
};
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.sum()); // Visualizzerà: 15
Creazione di gerarchie multilivello
Puoi creare gerarchie di oggetti più complesse a più livelli usando l'ereditarietà tramite prototipi.
Esempio:
const livingBeing = {
breathe() {
console.log('Respirare...');
}
};
const animal = Object.create(livingBeing);
animal.eat = function() {
console.log('Mangiare...');
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Camminare...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Abbaiare...');
};
dog.breathe(); // Visualizzerà: Respirare...
dog.eat(); // Visualizzerà: Mangiare...
dog.walk(); // Visualizzerà: Camminare...
dog.bark(); // Visualizzerà: Abbaiare...
GO TO FULL VERSION