Visualizzazione dei risultati da 1 a 3 su 3
  1. #1

    [Lungo] Dubbi sull'utilizzo del polimorfismo

    Buongiorno a tutti,

    ho iniziato da poco lo studio del Java, e sto affrontando vari aspetti del polimorfismo, soprattutto l'assegnazione di reference, il casting e i metodi virtuali.

    Ho creato, a scopo di esercizio, due classi: "Punto", che astrae un punto nello spazio bidimensionale, e "Punto3D" che astrae un punto nello spazio tridimensionale ed è estensione di "Punto". I metodi sono i soliti get e set, due costruttori (con e senza parametri), e un metodo "info" per la stampa a video delle proprietà. Quest'ultimo metodo, definito in "Punto", viene ridefinito nella sottoclasse "Punto3D".

    Infine c'è la terza classe che mi serve per eseguire i test, e questo è il codice

    codice:
    public class provaPunti {
     	public static void main(String args[]) {
     		Punto p2D = new Punto3D(10.0F,10.0F,0);
     		Punto3D p3D = new Punto3D();
      		System.out.println(p2D.info());
     		p3D = (Punto3D) p2D;
     		p3D.setZ(10.0F);
     		System.out.println(p2D.info());
     		System.out.println(p3D.info());
     	} 
    }
    Il mio scopo era quello di provare a capire meglio come funziona il fatto di assegnare un reference di una superclasse all'istanza di una sottoclasse, e poi eseguire il casting sul reference per utilizzare i metodi definiti per la prima volta nella sottoclasse (cosa altrimenti impossibile).

    Come prima cosa ho notato che sebbene il reference p2D si riferisca ad un oggetto "Punto", in realtà utilizza l'interfaccia pubblica della classe Punto3D, quindi devo utilizzare il costruttore che setta anche la dimensione sull'asse Z... mi chiedo se sia "elegante" definire, nella sottoclasse, un override del costruttore della superclasse. In questo modo potrei definire un punto. A funzionare funziona, ma mi chiedo quanto sia nella filosofia OOP.

    Seconda cosa: pensavo che l'istruzione p2D.info() mi avrebbe restituito le informazioni del reference come punto bidimensionale, invece ho visto che richiama il metodo in override, e non quello definito nella superclasse... riprendendo la definizione di metodo virtuale: "un metodo m si definisce virtuale quando è definito in una classe A, ridefinito in una sottoclasse B e invocato su un'istanza di B tramite un reference di A". Ok, questo mi chiarisce le idee... ma allora se assegno il reference alla superclasse attraverso l'istanza della sottoclasse, come faccio a invocare effettivamente il metodo definito nella superclasse e non il suo override? Insomma vorrei che l'istruzione p2D.info() mi dica che ho istanziato un punto bidimensionale, ma così mi dice - giustamente - che ho istanziato un punto tridimensionale.

    Terza cosa (la più grave, dato che non capisco proprio come mai succeda): l'istruzione p3D.setZ(10.0F) mi modifica anche la proprietà di p2D... in pratica le ultime due istruzioni mi restituiscono lo STESSO IDENTICO output... capisco che l'interfaccia è quella della classe "Punto3D", ma se il metodo setZ è invocato sul p3D, non capisco come faccia ad andare a modificare anche p2D, che a conti fatti è comunque un'altra variabile!

    Grazie a chiunque voglia illuminarmi!

    Davide.

    EDIT: come al solito, mettere le cose nero su bianco aiuta a fare un po' di luce... Ho capito il perché del terzo punto: l'istruzione p3D = (Punto3D) p2D assegna a p3D lo stesso indirizzo di p2D e ne modifica l'intervallo di puntamento, quindi a questo punto il programma non riesce più a riconoscere la differenza tra i due reference. Capisco che in ottica di programmazione tutto ciò non ha molto senso, ma si tratta di una cosa a scopo puramente didattico.

    Se volessi continuare su questa linea ed evitare di far confondere il programma, più che assegnare lo stesso indirizzo mi viene da pensare che dovrei realizzare un metodo che copia i valori... suggerimenti?

    Grazie ancora.

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: [Lungo] Dubbi sull'utilizzo del polimorfismo

    Originariamente inviato da davide.bass
    Ho creato, a scopo di esercizio, due classi: "Punto", che astrae un punto nello spazio bidimensionale, e "Punto3D" che astrae un punto nello spazio tridimensionale ed è estensione di "Punto".
    Questo è uno dei classici errori gravi che si commettono quando si inizia con l'usare l'ereditarietà. Che non va usata così!!!

    Una classe Gatto può estendere Animale (perché un gatto è-un animale) ... una classe Cubo può estendere Solido (perché un cubo è-un solido).
    Ma un punto tridimensionale .... non è un punto bidimensionale!!!

    Punto (nel senso di basta ... stop ... non ho nemmeno letto il resto che hai scritto perché comunque la base è già sbagliata in partenza!)
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Ciao andbin,

    sto studiando seguendo il "Manuale di Java 5" di Claudio De Sio Cesari (disponibile gratuitamente qui). In questo manuale l'utilizzo dell'ereditarietà è spiegato dall'inizio, soprattutto la regola del "è-un", che anche tu hai giustamente sottolineato.

    In un modulo del testo si chiede di realizzare un'applicazione per il calcolo della distanza tra due punti, e ti riporto quello che è scritto a pag. 229, dopo che l'autore ha scritto le due classi "Punto" e "Punto3D":

    ""
    Notiamo che, pur di utilizzare l'ereditarietà "legalmente", abbiamo violato la regola dell'astrazione. Infatti abbiamo assegnato l'identificatore "Punto" ad una classe che si sarebbe dovuta chiamare "Punto2D". Avrebbe senso chiamare la classe "Punto" solo dove il contesto dell'applicazione è chiaro. Per esempio in un'applicazione che permetta di fare disegni, la classe Punto così definita avrebbe avuto senso. Nel momento in cui il contesto è invece generare come nel nostro esempio, non è detto che un Punto debba avere due dimensioni. Ricordiamo che, per implementare il meccanismo dell'ereditarietà, lo sviluppatore deve testarne la validità, mediante la cosiddetta relazione "is a" ("è un"). Violando l'astrazione abbiamo potuto validare l'ereditarietà.
    ""

    Detto questo, e pur non essendo completamente d'accordo con l'autore, spero di averti reso un po' più chiaro il contesto nel quale ho implementato l'ereditarietà tra le classi... non avevo specificato tutto ciò non avendo ritenuto - in questo ambito - necessario avere consigli in tal senso.

    Ti chiedo, gentilmente, di andare avanti nella lettura del mio quesito originario... sono sempre pronto ad accogliere critiche e suggerimenti costruttivi.

    Grazie!

    Davide.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.