Newsgroup: it.comp.java
Titolo: Casting

Ciao a tutti
ho un problema di casting: vi do il codice:
class A{
  int par;
  public A(){}
}
class B extends A{
  float par;
  int par2;
  public B(){}
}
public class Prova{
 public Prova(){}
  public static void main(String args[]){
    A a=new A();
    B b=new B();
    a.par=5;
    b=(B)a;
    b.par2=2;
    System.out.println("B: "+b.par+"; "+b.par2+".");
  }
}
in compilazione non mi da problemi.
appena provo ad eseguirlo invece mi da il seguente errore:
Exception in thread "main" java.lang.ClassCastException: A
             at Prova.main(Prova.java: 16)
il mio problema è il seguente data una classe a ed una sua sottoclasse b, è
possibile copiare tutti gli attributi di a in b
"automaticamente" con qualcosa di simile a b=(B)a o devo per forza farlo a
mano con un metodo tipo
public B copyFromA(A a){...}?
anche se non sembra dall'esempio banale, ma è una questione di vitale
importanza, vi prego aiutatemi.
grazie 1000
ciaccio

public B copyFromA(A a){...}?
Devi costruire un metodo apposito, oppure inizializzare la "porzione A"
di B nel costruttore (se la copia ti serve una volta sola)
-- 
God is Real, unless declared Integer.
ObjectZone - 
http://space.tin.it/computer/csadun

 di B nel costruttore (se la copia ti serve una volta sola)
è quello che temevo. ;(
grazie mille.
ciao
ciaccio


Ciao,
secondo me e' l'approccio all'ereditarieta' che e' sbagliato:
un'oggetto o e' di un tipo o non lo e'! Per spiegarmi meglio ti faccio
l'esempio classico dei veicoli: si abbia la semplice gerarchia a
partire dalla classe dei "VeicoloAMotore", che si specializza nelle due
sottoclassi "Automobile" e "Camion". Un oggetto "a" della classe
Automobili e' anche un VeicoloAMotore e quindi un cast di "a" verso
VeicoloAMotore ha perfettamente senso, mentre non lo ha il contrario
(perche' un generico VeicoloAMotore dovrebbe essere un'Automobile?).
Fra l'altro ci sono anche non indifferenti problemi pratici (e nel tuo
caso ancora maggiori, dato che sovrascrivi un'attributo della classe A
(int par) con uno della sua sottoclasse B (float par)): ad esempio,
come potrebbe il compilatore generare del codice per convertire un
oggetto A in uno B, senza che qualcuno gli dica come cambiare int par
in float par o in int par2?
Si noti che invece le cose funzionano se si scrive una cosa del genere:
A a=new B();
B b=null;
a.par=5;
b=(B)a;
b.par2=2;
System.out.println("B: "+((A)b).par+"; "+b.par+"; "+b.par2+".");
(da' come risultato B: 5; 0.0; 2.)
Riassumendo, un oggetto deve essere di un tipo specifico fin dalla sua
creazione. Se invece lo scopo e' quello di ottenere un oggetto che
evolve nel tempo, secondo me la cosa migliore e' costruirlo per
aggregazione, piuttosto che con l'ereditarieta (Quindi l'automobile e'
un veicolo a motore a cui si aggiungono 4 ruote, gli si da' una certa
dimensione, ecc...), cercando di partire dal tipo piu' specifico
possibile al momento della creazione dell'oggetto.
Un saluto
  Lucio
--
(
  Lucio Benfante
 
http://www.dei.unipd.it/~benfante
                                          )
Sent via Deja.com 
http://www.deja.com/
Before you buy.

ciao e grazie mille della risposta, però credo di non essermi spiegato bene.
rimango nell'esempio del VeicoloAMotore.
io ho un'istanza v di un VeicoloAMotore ed un'istanza m di una Macchina.
adesso voglio inizializzare m con alcuni parametri gi v: esempio
m come v va a benzina.
m come v ha delle ruote.
m come v è prodotta in italia
ecc..
diciamo che tutti i valori degli attributi di v vanno bene anche per m.
allora vorrei fare una cosa del tipo
m=(Macchina)v
e poi andarmi a settare solo gli attributi restanti
esempio dimensione bagagliaio.
e per fare ciò vorrei evitare di fare per ogni attributo un'operazione del
genere
m.setAttributo1(v.getAttributo1());
spero di essermi spiegato meglio.
grazie 1000
ciao
ciaccio

,

Un soluzione semplice e' quella di dotare la classe Macchina di un
costruttore che abbia come parametro un veicolo a motore.
Infatti ha poco senso scivere una cosa del tipo:
m=(Macchina)v;
dato che v non e' una Macchina, ma semplicemente un VeicoloVMotore
(mentre e' vero il contrario: una Macchina e' anche un VeicoloAMotore).
Ha senso invece costruire una macchina a partire da un generico veicolo
a motore:
m = new Macchina(v);
Dal punto di vista pratico la cosa si riduce a poco codice in piu':
class VeicoloAMotore {
  // attributi e metodi di un veicolo a motore
}
class Macchina extends VeicoloAMotore {
  public Macchina(VeicoloAMotore v) {
    /* richiama il costruttore di VeicoloAMotore
       con v.attr1 otteniamo gli attributi public o protected
       chiamando conv.getAttr2() quelli private
    */
    super(v.attr1, v.getAttr2(),....);
    // altre operazioni del costruttore
  }
  // altri attributi e metodi di una macchina
}
Eventualmente si puo' semplificare ulteriormente dotando anche
VeicoloAMotore di un costruttore che abbia come parametro un
VeicoloAMotore (il cosiddetto "costruttore di copia" del C++) e
chiamare semplicemente super(v) nel costruttore di Macchina (sara' poi
compito del costruttore di VeicoloAMotore assegnare i corretti valori).
