7. Polimorfismo
Grazie all’ereditarietà è possibile definire due aggettivi per il tipo degli oggetti:
- Tipo statico: è il tipo che viene assegnato all’oggetto al momento della sua dichiarazione
- Tipo dinamico: è il tipo che l’oggetto assume a runtime.
Definizione di polimorfismo
Ex.
public class Car{
public static void start(Car p){
if(p.canStart()){
p.turnOn();
}
public static void main(String args[]){
Car mycar = new ElectricCar("Tesla");
start(mycar);
}
}
Nella prima riga del metodo main
viene dichiarato l’oggetto mycar
: il suo tipo statico è Car
, mentre il suo tipo dinamico, subito dopo l’esecuzione di quella riga di codice, è ElectricCar
ed esso può comunque cambiare con l’esecuzione del programma.
Questo è un esempio di polimorfismo: è l’abilità che un elemento sintattico può usare per riferirsi a tipi differenti.
In Java, una variabile referenziata di tipo T può fare riferimento al tipo T oppure a un suo sottotipo.
Tipi statici e dinamici
Il tipo statico viene definito dalla dichiarazione, mentre quello dinamico viene definito dal costruttore usato per costruire l’oggetto.
Ex. Siano le due classi A e B, erede di A. Sia l’oggetto o, dichiarato come A o;
: il suo tipo statico è A. Il tipo dinamico di o può essere:
- uguale al suo tipo statico:
A o = new A();
- uguale a un tipo di una sottoclasse di A:
A o = new B();
- Non si può avere una situazione diversa da queste!
NB: L’assegnamento tra due oggetti viene considerato come errore a compile time se i tipi statici non sono uguali.
Chiamata dei metodi
Car mycar = new ElectricCar();
mycar.canStart(); // OK, chiamo un metodo di Car
mycar.turnOn(); // OK, chiamo il metodo di ElectricCar
mycar.recharge(); // KO, recharge non è un metodo di Car
ElectricCar yourcar = new ElectricCar();
yourcar.recharge(); // OK, chiamo un metodo di Car
Overloading
In Java si ha overloading quando due o più metodi hanno lo stesso nome, ma hanno parametri diversi.
public class Point2D{
public float distance(Point2D p){...}
}
public class Point3D extends Point2D{
public float distance(Point3D p){...}
}
Binding dinamico
In Java, ogni volta che scriviamo x.m(P)
(dove x è un oggetto, m un suo metodo e P la lista di parametri forniti al metodo), la JVM deve scegliere quale implementazione del metodo m utilizzare: questa scelta viene fatta in base al tipo dinamico dell’oggetto x e NON in base al suo tipo statico.
Il compilatore a runtime sceglie in base al tipo dinamico dell’oggetto l’implementazione del metodo che più si avvicina al metodo chiamato.
public class UsaCar {
public static void start(Car a) {
a.turnOn(); //defined in ElectricCar
}
public static void main(String args[]) {
Car a1 = new Car("Ford");
Car a2 = new ElectricCaral("T");
a1.turnOn();
// at run-time call implementation of Car
a2.turnOn();
// at run-time call implementation of ElectricCar
start(a2);
// only at run time you can know the actual type
}
}