10.1 Fondamenti del polimorfismo
Il polimorfismo è uno dei concetti chiave della programmazione orientata agli oggetti (OOP). In senso generale, il polimorfismo consente agli oggetti di diverse classi di gestire i dati utilizzando la stessa interfaccia. Nel contesto di JavaScript significa che oggetti diversi possono avere metodi con lo stesso nome e questi metodi possono essere invocati sugli oggetti senza conoscere il loro tipo specifico.
Tipi di polimorfismo
In JavaScript i principali tipi di polimorfismo sono:
1. Polimorfismo ad-hoc (ad-hoc polymorphism):
- Polimorfismo dei metodi, invocazione di metodi con lo stesso nome per oggetti di tipi diversi
- Esempi includono sovraccarico di funzioni e operatori (che non è supportato direttamente in JavaScript, ma può essere simulato)
2. Polimorfismo per sottotipo (Subtype polymorphism):
- Polimorfismo per sottotipo o inclusione, quando oggetti di classi diverse ereditano da una stessa classe base e possono essere trattati come oggetti della classe base
- Questo è il tipo principale di polimorfismo, realizzato attraverso ereditarietà e interfacce
Vantaggi del polimorfismo:
- Semplificazione del codice: il polimorfismo consente di scrivere codice più flessibile e generico che può funzionare con diversi tipi di oggetti senza conoscerne i tipi specifici.
- Estensibilità: il polimorfismo facilita l'aggiunta di nuovi tipi e comportamenti al sistema senza la necessità di modificare il codice esistente.
- Supporto: il polimorfismo promuove una migliore separazione delle responsabilità e aumenta la leggibilità e la manutenzione del codice.
10.2 Esempi di polimorfismo in JavaScript
Polimorfismo per sottotipo attraverso l'ereditarietà
Esempio 1: Gestione di diversi tipi di oggetti tramite un'interfaccia
In questo esempio, la funzione playWithAnimal
accetta un oggetto di tipo Animal
e chiama il metodo makeSound
. Gli oggetti Dog
e Cat
, che ereditano da Animal
, sovrascrivono il metodo makeSound
, e chiamando il metodo su ciascun oggetto si ottiene un risultato diverso.
class Animal {
makeSound() {
console.log('Some generic sound');
}
}
class Dog extends Animal {
makeSound() {
console.log('Woof!');
}
}
class Cat extends Animal {
makeSound() {
console.log('Meow!');
}
}
function playWithAnimal(animal) {
animal.makeSound();
}
const dog = new Dog();
const cat = new Cat();
playWithAnimal(dog); // Risulterà: Woof!
playWithAnimal(cat); // Risulterà: Meow!
10.3 Polimorfismo attraverso interfacce (Duck Typing)
In JavaScript non c'è supporto nativo per le interfacce, come in altri linguaggi, ad esempio TypeScript o Java. Invece si usa un approccio chiamato "duck typing". Ciò significa che un oggetto è considerato conforme all'interfaccia se possiede i metodi e le proprietà richieste, indipendentemente dal suo tipo specifico o dall'ereditarietà.
Regola dell'anatra (duck): se qualcosa sembra un'anatra, nuota come un'anatra e fa il verso di un'anatra, allora probabilmente è un'anatra.
Esempio 2: Utilizzo del duck typing
In questo esempio, la funzione takeOff
accetta qualsiasi oggetto che abbia il metodo fly
. Gli oggetti Bird
e Airplane
implementano il metodo fly
, quindi possono essere passati a takeOff
.
class Bird {
fly() {
console.log('Flying...');
}
}
class Airplane {
fly() {
console.log('Jet engine roaring...');
}
}
function takeOff(flyingObject) {
flyingObject.fly();
}
const bird = new Bird();
const airplane = new Airplane();
takeOff(bird); // Risulterà: Flying...
takeOff(airplane); // Risulterà: Jet engine roaring...
10.4 Polimorfismo attraverso le funzioni
In JavaScript le funzioni sono oggetti di prima classe e possono essere passate e utilizzate per implementare un comportamento polimorfico.
Esempio 3: Polimorfismo attraverso le funzioni
In questo esempio, la funzione greet
accetta un'altra funzione come argomento e la chiama. Questo permette di utilizzare diverse funzioni per eseguire azioni differenti.
function greetMorning() {
console.log('Good morning!');
}
function greetEvening() {
console.log('Good evening!');
}
function greet(greetingFunction) {
greetingFunction();
}
greet(greetMorning); // Risulterà: Good morning!
greet(greetEvening); // Risulterà: Good evening!
10.5 Polimorfismo attraverso sovraccarico del metodo (Simulazione)
JavaScript non supporta direttamente il sovraccarico dei metodi, come alcuni altri linguaggi di programmazione. Tuttavia, si può simulare il sovraccarico dei metodi utilizzando gli argomenti delle funzioni e il controllo dei loro tipi.
Esempio 4: Simulazione del sovraccarico del metodo
In questo esempio, il metodo add
accetta due argomenti ed esegue diverse azioni a seconda dei loro tipi. Se gli argomenti sono numeri, il metodo li somma. Se gli argomenti sono array, il metodo li concatena.
class Calculator {
add(a, b) {
if (typeof a === 'number' && typeof b === 'number') {
return a + b;
} else if (Array.isArray(a) && Array.isArray(b)) {
return a.concat(b);
} else {
throw new Error('Invalid arguments');
}
}
}
const calc = new Calculator();
console.log(calc.add(1, 2)); // Risulterà: 3
console.log(calc.add([1, 2], [3, 4])); // Risulterà: [1, 2, 3, 4]
GO TO FULL VERSION