A parte l'esempio che hai posto, che è puramente didattico, la differenza sta proprio nel fatto che dichiarando un oggetto come tipo "Superclasse" non possono essere invocati su di esso tutti i metodi specifici della sottoclasse, per il semplice fatto che il compilatore non sa a priori di quale sottoclasse sia l'oggetto (ce ne possono essere diversi).
Forse con un esempio diverso la cosa risulta più chiara:
Classe: Figura
Sottoclassi: Triangolo, Rettangolo, Cerchio.
Ipotizzando che Figura metta a disposizione questi metodi astratti:
- calcolaPerimetro();
- calcolaArea();
ciascuna sottoclasse li implementerà a suo modo:
Triangolo
Area: base * altezza / 2;
Perimetro: lato1 + lato2 + lato3;
Rettangolo
Area: base * altezza;
Perimetro: (base + altezza) * 2;
Cerchio
Area: (raggio ^ 2) * PI;
Perimetro: raggio * 2 * PI;
Ora vediamo questa situazione:
codice:
Figura f1 = new Triangolo();
Figura f2 = new Rettangolo();
Figura f3 = new Cerchio();
Su tutti gli oggetti (f1, f2, f3) io posso invocare i metodi calcolaPerimetro() e calcolaArea():
codice:
f1.calcolaArea();
f2.calcolaArea();
f3.calcolaArea();
Ognuno dei quali calcolerà l'area nel modo corretto in base alla "figura reale".
Ma posso io invocare, ad esempio, il metodo "getRaggio()" (che posso supporre esista nella classe Cerchio) sugli oggetti f1 e f2? Avrebbe senso? E come fa il compilatore a sapere che la chiamata sull'oggetto f1 è errata, mentre su f3 è corretta visto che entrambi gli oggetti sono dichiarati di tipo "Figura"?
In una situazione come la seguente, quindi, è impossibile richiamare i metodi specifici per ciascuna sottoclasse, proprio perchè il compilatore non può conoscerli in anticipo. E', invece, lecito richiamare uno dei due metodi "calcolaPerimetro()" o "calcolaArea()" perchè sono comuni a tutti gli oggetti di tipo Figura e, di conseguenza, anche a tutti gli oggetti delle sottoclassi.
La tua prossima domanda sarà: allora a che serve dichiarare un oggetto di tipo "Figura", visto che non posso accedere ai metodi specifici?
Risposta: non in tutte le situazioni puoi sapere a priori che tipo di Figura stai maneggiando. Esempio:
codice:
// Questo metodo fa parte di una classe che non c'entra nulla con le figure
// ma le usa in modo appropriato
public double differenzaAree(Figura f1, Figura f2) {
return f1.calcolaArea() - f2.calcolaArea();
}
Il metodo qui sopra è molto generico: calcola la differenza fra le aree di due figure qualsiasi e può essere richiamato in tanti modi:
codice:
Rettangolo r = new Rettangolo();
Triangolo t = new Triangolo();
Cerchio c = new Cerchio();
System.out.println( differenzaArea(r, r) );
System.out.println( differenzaArea(r, c) );
System.out.println( differenzaArea(r, t) );
System.out.println( differenzaArea(c, c) );
System.out.println( differenzaArea(c, t) );
System.out.println( differenzaArea(t, t) );
...
Non importa che tipo di oggetto gli viene passato: lui lavora in modo corretto!
Ciao.