Storia della questione:
Il polimorfismo è uno dei principi chiave della programmazione orientata agli oggetti (OOP), supportato in Java sin dalla sua creazione. Permette a un oggetto di comportarsi in modi diversi a seconda del suo tipo effettivo durante l'esecuzione del programma, anche se si utilizza un riferimento di tipo base.
Problema:
Senza polimorfismo, il codice diventa rigido, spesso appaiono costruzioni ridondanti di tipo switch-case o if-else per lavorare con oggetti di diversi tipi. Questo complica la manutenzione e l'estensione del codice. Il polimorfismo risolve la necessità di scrivere codice ripetitivo per tipi diversi.
Soluzione:
Il polimorfismo in Java è realizzato attraverso l'ereditarietà e le interfacce. Permette di:
Esempio di codice:
class Animal { void speak() { System.out.println("Animal speaks"); } } class Dog extends Animal { @Override void speak() { System.out.println("Dog barks"); } } class Cat extends Animal { @Override void speak() { System.out.println("Cat meows"); } } public class PolyDemo { public static void main(String[] args) { Animal a1 = new Dog(); Animal a2 = new Cat(); a1.speak(); // Dog barks a2.speak(); // Cat meows } }
Caratteristiche chiave:
Qual è la differenza tra overloading e overriding dei metodi nel polimorfismo?
L'overloading è la definizione di più metodi con lo stesso nome ma con firme diverse all'interno della stessa classe. L'overriding è la definizione di un metodo nella sottoclasse con la stessa firma di quella nella classe genitore.
class Example { void foo(int x) {} void foo(String y) {} // questo è overloading } class Base { void foo() {} } class Child extends Base { @Override void foo() {} // questo è overriding }
Può esistere polimorfismo senza ereditarietà?
Nel senso classico, in Java, no: il polimorfismo richiede l'esistenza di una gerarchia di ereditarietà o di un'interfaccia implementata.
È possibile chiamare metodi della sottoclasse da un riferimento alla classe genitore?
È possibile chiamare solo metodi definiti nella classe genitore o sovrascritti nella sottoclasse. I metodi che esistono solo nella sottoclasse non possono essere chiamati senza un cast di tipo.
Animal a = new Dog(); a.speak(); // è possibile // a.fetch(); // errore di compilazione, anche se Dog ha il metodo fetch()
In un progetto sono state implementate classi Dog, Cat, Cow, ma il codice utilizzato operava direttamente con i tipi, chiamando metodi tramite cast espliciti e instanceof:
Vantaggi:
Svantaggi:
Ereditarietà di Animal con speak() virtuale. Tutta l'interazione avviene tramite il tipo base Animal.
Vantaggi:
Svantaggi: