Il terzo elemento fondamentale della programmazione ad Oggetti è il polimorfismo. Letteralmente, la parola polimorfismo indica la possibilità per uno stesso oggetto di assumere più forme.
Per rendere l'idea più chiara, utilizzando ancora una volta un esempio del mondo reale, si pensi al diverso comportamento che assumono un uomo, una scimmia e un canguro quando eseguono l'azione del camminare. L'uomo camminerà in modo eretto, la scimmia in maniera decisamente più goffa e curva mentre il canguro interpreterà tale azione saltellando.
Riferendoci ad un sistema software ad oggetti, il polimorfismo indicherà l'attitudine di un oggetto a mostrare più implementazioni per una singola funzionalità.
Polimorfismo: un esempio pratico
Supponiamo di voler costruire un sistema software in grado di disegnare delle figure geometriche. Per tale sistema avremo definito una classe padre chiamata FiguraGeometrica dalla quale avremo fatto derivare tutte le classi che si occupano della gestione di una figura geometrica ben precisa. Per maggiore chiarezza riportiamo quanto detto nel diagramma seguente:
Quando l'utente desidera rappresentare una di tali figure, sia essa una linea, un cerchio o un rettangolo, egli eseguirà una determinata azione che produrrà l'invio al sistema di un messaggio che, a sua volta, scatenerà l'invocazione del metodo disegnaFigura della classe FiguraGeometrica..
Con l'utilizzo del polimorfismo, il sistema è in grado di capire autonomamente quale figura geometrica debba essere disegnata ed invocarne direttamente il metodo disegnaFigura appartenente alla classe figlia coinvolta.
In un sistema non ad oggetti (e, quindi, senza la possibilità di utilizzare il polimorfismo) un simile comportamento necessiterebbe, dal punto di vista del codice, di un costrutto tipo switch - case come il seguente, tutto implementato all'interno di un'unica classe:
function disegnaFigura()
{
CASE FiguraGeometrica.Tipo
Case 'Cerchio'
FiguraGeometrica.DisegnaCerchio()
Case 'Rettangolo'
FiguraGeometrica.DisegnaRettangolo()
Case 'Linea'
FiguraGeometrica.DisegnaLinea()
END CASE
}
Al contrario, con l'utilizzo del polimorfismo, il tutto si riconduce ad una semplice chiamata del tipo:
function Disegna(
{
FiguraGeometrica.disegnaFigura()
}
Dietro una semplice codifica di questo tipo si nasconde tutta la potenza del polimorfismo: il sistema chiama in modo automatico il metodo disegnaFigura() dell'oggetto che è stato selezionato dall'utente, senza che ci si debba preoccupare se si tratti di cerchio, rettangolo o linea. In altre parole, potremmo dire che il polimorfismo consente ad oggetti differenti (ma collegati tra loro) la flessibilità di rispondere in modo differente allo stesso tipo di messaggio.
I vantaggi del polimorfismo
Uno dei maggiori benefici del polimorfismo, come in effetti di un po' tutti gli altri principi della programmazione ad oggetti, è la facilità di manutenzione del codice. Per rendere l'idea, basta domandarsi cosa accadrebbe se l'applicazione precedente volesse implementare anche la funzionalità di disegnare un triangolo.
Nel caso non polimorfico, bisognerebbe aggiungere una nuova funzione DisegnaTriangolo all'oggetto FiguraGeometrica e poi modificare la funzione DisegnaFigura globale, esaminata in precedenza, aggiungendo ad essa due nuove righe per gestire il caso della nuova tipologia di figura da inserire.
Con il polimorfismo invece, molto più semplicemente, basterà creare l'oggetto Triangolo e implementare in esso il metodo disegnaFigura(). L'invocazione di quest'ultimo avverrà, come per le altre figure geometriche già definite, in modo del tutto trasparente e automatico.
Implemetare il polimorfismo
Ecco come si implementa il polimorfismo in alcuni dei linguaggi orientati agli oggetti per il web.