Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    726

    [JAVA] Cast applicati ai metodi o agli argomenti

    Ciao,
    devo assolutamente capire bene come java gestisce le regole di sottotipaggio e come e perchè alcune istruzioni errare vengono segnalate a tempo di compliazione o a tempo di esecuzione.

    Ad esempio:
    codice:
    public class Classe1
    {
     public void metodo() { System.out.println("CIAO A TUTTI");}
     public void metodo2() { System.out.println("CIAO A TUTTI e 2");
     }
    }
    codice:
    public class Classe2 extends Classe1
    {
     public void metodo() { System.out.println("METODO RISCRITTO");
     }
     
     public static void main(String[] args)
     {
      Classe2 c = new Classe2();
      (Classe1 c ).metodo();
     }	
    }
    Prendiamo ad esempio la seguente istruzione: ((Classe1) c ).metodo();
    Da quello che ho capito faccio il cast di c a Classe1, che è padre di Classe2.
    Quindi mi aspetterei che c ora non venga più considerato di Classe2 ma di Classe1, potendo quindi invocare solo i metodi che stanno dentro a Classe1.
    Ma non è cosi, infatti se lancio il codice cosi coome l'ho postato in output ricevo "METODO RISCRITTO". Perchè?


    Un'altra cosa importante che vorrei capire bene è poter stabilire quando java verifica la legalità ad esempio per l'invocazione di un metodo.
    Se io ad esempio scrivo cosi:
    Classe1 c1 = new Classe1();
    c.metodo();

    so che il controllo viene fatto a tempo di complicazione (non ci sono cast).
    Posso dire quindi che quando non ci sono cast (di qualsiasi tipo) tra classi con una relazione la verifica della legalità dell'invocazione dei metodi viene fatta a tempo di compilazione?

    Per piacere, illuminatevi, sono decisamente confuso.

    Grazie

  2. #2
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320

    Re: [JAVA] Cast applicati ai metodi o agli argomenti

    Originariamente inviato da Downloader
    Prendiamo ad esempio la seguente istruzione: ((Classe1) c ).metodo();
    Da quello che ho capito faccio il cast di c a Classe1, che è padre di Classe2.
    Quindi mi aspetterei che c ora non venga più considerato di Classe2 ma di Classe1, potendo quindi invocare solo i metodi che stanno dentro a Classe1.
    Ma non è cosi, infatti se lancio il codice cosi coome l'ho postato in output ricevo "METODO RISCRITTO". Perchè?
    Perchè un cast non "trasforma" un oggetto in un altro, ma forza semplicemente a vedere l'oggetto come se fosse di un altro tipo. Nel tuo caso particolare, non ha alcun senso un cast del genere perchè Classe2, derivando da Classe1, è già di per sè un oggetto di Classe1 (ereditarietà).
    Quello che hai fatto, riscrivendo il metodo metodo() è stato sottoporre ad override tale metodo. Lo hai riscritto, "perdendo", quindi, il riferimento al metodo originario. Questo si chiama "polimorfismo": hai un solo metodo per comportamenti diversi. L'oggetto (reale) su cui vai ad invocare tale metodo è sempre un oggetto di tipo Classe2 (che tu lo stia guardando come Classe2 o Classe1) quindi verrà richiamato il metodo più adatto al tipo di oggetto (quello a lui più vicino).

    Un'altra cosa importante che vorrei capire bene è poter stabilire quando java verifica la legalità ad esempio per l'invocazione di un metodo.
    Se io ad esempio scrivo cosi:
    Classe1 c1 = new Classe1();
    c.metodo();

    so che il controllo viene fatto a tempo di complicazione (non ci sono cast).
    Posso dire quindi che quando non ci sono cast (di qualsiasi tipo) tra classi con una relazione la verifica della legalità dell'invocazione dei metodi viene fatta a tempo di compilazione?

    Per piacere, illuminatevi, sono decisamente confuso.

    Grazie
    Non è la presenza di cast o meno che determina se il controllo deve essere fatto a tempo di compilazione o a tempo di esecuzione.
    Prendiamo questo esempio:
    codice:
    String s = "13";
    Integer i = (Integer) s;
    Questo codice genera un errore a tempo di compilazione: Inconvertible types.

    Il controllo sull'invocazione di un metodo è sempre fatta a tempo di compilazione. Quando viene invocato un metodo viene sempre controllato il tipo dell'oggetto sul quale viene fatta l'invocazione. Se il tipo di dato non prevede l'esistenza di quel metodo è sempre il compilatore che se ne accorge.

    Forse stai confondendo il controllo con l'invocazione vera e propria.

    Ciò che può essere fatto a tempo di esecuzione è l'invocazione di un metodo piuttosto che un altro, ma questo riguarda il polimorfismo, non l'ereditarietà.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  3. #3
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    726
    Perchè un cast non "trasforma" un oggetto in un altro, ma forza semplicemente a vedere l'oggetto come se fosse di un altro tipo. Nel tuo caso particolare, non ha alcun senso un cast del genere perchè Classe2, derivando da Classe1, è già di per sè un oggetto di Classe1 (ereditarietà).
    Quello che hai fatto, riscrivendo il metodo metodo() è stato sottoporre ad override tale metodo. Lo hai riscritto, "perdendo", quindi, il riferimento al metodo originario. Questo si chiama "polimorfismo": hai un solo metodo per comportamenti diversi. L'oggetto (reale) su cui vai ad invocare tale metodo è sempre un oggetto di tipo Classe2 (che tu lo stia guardando come Classe2 o Classe1) quindi verrà richiamato il metodo più adatto al tipo di oggetto (quello a lui più vicino).
    Intanto grazie per la risposta.
    Però temo di non aver capito bene quello che vuoi dire.

    Se io con il cast forzo java a vedere un oggetto A come se fosse di un altro tipo (B) allora non dovrei poter usare solo e soltanto i metodi della classe B?

  4. #4
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Originariamente inviato da Downloader
    Intanto grazie per la risposta.
    Però temo di non aver capito bene quello che vuoi dire.

    Se io con il cast forzo java a vedere un oggetto A come se fosse di un altro tipo (B) allora non dovrei poter usare solo e soltanto i metodi della classe B?
    Non nel senso che intendi tu.

    Forzando a vedere un oggetto B come se fosse di tipo A, quello che ottieni è "limitare l'utilizzo" di B con i soli metodi esposti da A. Questo non significa che utilizzi i metodi di A, ma che utilizzi solo i metodi che A espone.

    Il tuo oggetto rimane sempre di tipo "Classe2", ma, castandolo a "Classe1" ne limiti l'utilizzo ai soli metodi che vengono esposti dalla classe "Classe1". Quindi puoi utilizzare il metodo metodo() in quanto esso è presente anche nella classe "Classe1". Ma essendo che Classe2 ha anch'essa un metodo chiamato metodo() viene invocato quello, perchè più vicino all'oggetto su cui stai operando. E questo è corretto dal punto di vista logico.

    Se vogliamo fare un esempio in senso lato, utilizzando gli animali, possiamo ipotizzare di avere una classe generica "Animale" dalla quale vengono derivate le classi "Topo" e "Balena".

    La classe "Animale" espone il metodo muoviti() che verrà implementato in modo differente da Topo e da Balena.

    Ma se tu hai un oggetto di tipo Balena e lo casti ad Animale, non puoi pretendere che, invocando muoviti(), la balena si metta a camminare, anche se a livello di Animale hai definito lo spostamento come una camminata... la balena (anche se vista come Animale) nuoterà.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  5. #5
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    726
    Adesso credo di aver capito!

    Posso chiederti altre due cose?

    1)
    codice:
    Classe2 c2 = new Classe2();
    
    c2.metodo(); // a tempo di compilazione so gia che dovrò usare il metodo di c2
    
    ((Classe1) c2).metodo();
     // anche qua la scelta del metodo da lanciare sarà fatta a tempo di compilazione, no?
    2)
    ((Classe1) c2).metodo();
    si dovrebbe chiamare DownCast, giusto?
    Cos'è un UpperCast invece, e in cosa differisce dal precedente?


    Grazie 1000 per il tuo supporto, mi stai dando una grossa mano

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    1) La verifica di correttezza avviene a tempo di compilazione, la scelta sarà fatta a tempo di esecuzione. A tempo di compilazione non è possibile sapere a priori quale tipo di oggetto verrà effettivamente istanziato (anche se in quel caso è possibile prevedere un'ottimizzazione, dato che l'oggetto è chiaramente di tipo Classe2).

    2) Un downcast è un cast da classe derivata verso classe base. Generalmente una cosa del genere è del tutto superflua. Il contrario, l'upcast, invece è molto utile quando viene utilizzata l'ereditarietà per generalizzare un metodo. Ad esempio, potrei avere un metodo che accetta oggetti di tipo Figura, al cui interno dovrò discriminare sul tipo effettivo per avere accesso a metodi particolari di ciascuna classe.

    Vediamo un piccolo esempio. Qui suppongo di avere una classe Figura che espone i metodi "calcolaArea()" (virtuale, che verrà implementato da ciascuna sottoclasse concreta) e "getTipo()" che mi dice che tipo di figura è.
    codice:
    public void mostraDettagliArea(Figura f) {
       System.out.println("La figura è un " + f.getTipo());
       System.out.println("L'area è: " + f.calcolaArea());
       if (f instanceof Cerchio) {
          System.out.println("Il centro del cerchio è: " + ((Cerchio) f).getCentro());
       }
    }
    La classe Cerchio mette a disposizione un metodo chiamato "getCentro()" che mi restituisce una stringa con le coordinate del cerchio in un ipotetico piano cartesiano... In questo caso sono obbligato a effettuare un upcast, perchè non tutte le figure hanno un centro e non tutte le figure, quindi, hanno un metodo "getCentro()".


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  7. #7
    Utente di HTML.it
    Registrato dal
    Nov 2003
    Messaggi
    726
    Perfetto!
    Grazie 1000, sei stato gentilissimo e chiarissimo

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 © 2025 vBulletin Solutions, Inc. All rights reserved.