Originariamente inviato da Felixfree
1) Perchè dichiari come "public" la classe astratta "Figura" e le sottoclassi che la estendono come "Triangolo", "Quadrato" e "Cerchio"? Intendo sapere se c'è un motivo che può indurre alla dichiarazione "public" rispetto a come ho fatto io e se la soluzione da me adottata può non andar bene per qualche motivo.
Mah... il motivo di dichiarare o meno public le classi serve per diversi motivi: la loro visibilità all'esterno del package o della classe stessa (nel caso di classi interne). In genere, se non ci sono motivi particolari per dichiarare una classe privata, la si dichiara public oppure, come hai fatto te, senza modificatore.
L'unica accortezza da prendere è la seguente: se una classe viene dichiarata public deve risiedere in un file .java separato (tranne, ovviamente, le classi interne ad altre classi).

2) Inoltre la dichiarazione di queste classi come "public" comporta che esse devono essere memorizzate in file separati del tipo Triangolo.java, Quadrato.Java e Cerchio.java... o mi sbaglio? Io per adesso ho sempre memorizzato tutte le classi nel solito file che compilo ed eseguo con i comandi "javac" e "java".
Esattamente... l'ho detto anche sopra. Io di solito preferisco separare le varie classi in file diversi, in modo da poterle localizzare più facilmente quando il progetto si fa più grande. Quando si ha a che faer con tante classi è bene saperle localizzare con precisione, per poterle andare a modificare in caso di necessità.

3) Ho letto che un metodo di tipo astratto dichiarato in una classe abstract deve essere sempre dichiarato abstract anch'esso. Perchè tu non dichiari come abstract il metodo calcola?
Io non l'ho sentito dire, ma potrebbe anche essere. Mi dovrò documentare maggiormente. Comunque, se una classe è abstract e contiene dei metodi non implementati automaticamente essi sono considerabili abstract. Credo che la differenza sia più che altro di tipo logico e/o semantico. In teoria, infatti, una classe abstract può implementare dei metodi, quindi il dichiarare abstract uno o più metodi agevola la distinzione in fase di scrittura del codice.

4) Nel metodo main ho riportato due modi, entrambi provati, di istanziare gli oggetti: quello commentato è del tipo indicato da te, mentre quello attualmente utilizzato richiama per certi versi una questione trattata all'inizio della discussione riguardo il dispatch. Entrambi funzionano e danno il risultato atteso: mi chiedo quindi quale sia la differenza e con quale criterio scegliere un modo o l'altro?
Ti dirò. Il metodo attualmente in uso in pratica non si usa mai. Non serve a niente, se non a scopo puramente didaticco, per evidenziare il fatto che si può, ovviamente, istanziare un oggetto di un certo tipo, utilizzando il costruttore di uno dei tipi figli. Questo perchè un figlio è sempre un'istanza della classe madre, mentre non è vero il contrario. La differenza, comunque, è evidente nel momento in cui le classi figlie aggiungano delle caratteristiche che la classe madre non ha: per esempio, la classe Triangolo può prevedere un metodo che stampa l'altezza del triangolo, che è assolutamente inutile nella classe Cerchio. Entrambe le due classi sono figlie di Figura, quindi è possibile istanziare due oggetti nel seguente modo:
codice:
Figura triangolo = new Triangolo(3, 6);
Figura cerchio = new Cerchio(10);
però se proviamo ad eseguire l'istruzione seguente, verrà generato un errore:
codice:
cerchio.stampaAltezza();
in quanto la classe Cerchio non possiede tale metodo. Da notare che anche la seguente istruzione genera un errore:
codice:
triangolo.stampaAltezza();
benché la classe Triangolo implementi il metodo stampaAltezza(). Questo perchè, a priori, la classe Figura non implementa tale metodo e l'oggetto è dichiarato per essere un oggetto della classe Figura. In questo caso, per poter richiamare il metodo che l'oggetto effettivamente possiede (essendo un oggetto Triangolo), è necessario un cast esplicito:
codice:
((Triangolo) triangolo).stampaAltezza();

Se con calma puoi rispondere a questi quesiti può essere che risulti utile anche ad altri utenti del forum, poichè vedo che questi temi per i principianti sono difficili da capire.
Mille grazie!
Effettivamente questi sono i concetti fondamentali su cui si basa la programmazione Orientata agli Oggetti, una volta entrati in testa, è certo che un grande passo in avanti è stato compiuto e si può cominciare a padroneggiare più agevolmente gli oggetti e si possono cominciare a sfruttare le loro caratteristiche.


Ciao.