Newsgroup: it.comp.java
Titolo: problemi di ereditarietà

salve a tutti,
ho il seguente problema:
public class Pippo(){
   public void Pippo(){
   }
   public void initialize(){
     loadConf();
   }
   public void loadConf(){
     System.out.println("Sono nella superClasse");
   }
}
public class Paperoga() extend Pippo{
   public void Paperoga(){
   }
   public void initialize(){
     super.loadConf();
     loadConf();
   }
   public void loadConf(){
     System.out.println("Sono nella subClasse");
   }
}
Quando lancio Paperoga.initialize(), io mi aspetto che Java mi ritorni:
[OUTPUT]
Sono nella superClasse
Sono nella subClasse
in realtà mi ritorna:
[OUTPUT]
Sono nella subClasse
Sono nella subClasse
Qundi vuol dire che il superMetodo Initialize richiama il loadconf della 
subClase... ma perchè ????
-----------------------------------
Vi passo anche queste informazioni:
-----------------------------------
se metto i due loadConf a private mi ritorna l'output giusto:
[OUTPUT]
Sono nella superClasse
Sono nella subClasse
-------------------------------------
se li metto tutte e due a protected:
[OUTPUT]
Sono nella subClasse
Sono nella subClasse
-------------------------------------
se metto il supermetodo a private ed il sub a protected mi ritorna:
[OUTPUT]
Sono nella superClasse
Sono nella subClasse
Qualè il meccanismo che discrimina quale metodo chiamare in caso di 
classi ereditate e metodi sovrascritti ???
Grazie mille :-))

Ho provato il tuo codice, naturalmente correggendo qualche piccolo errore di
sintassi, e a me restituisce il risultato aspettato:
sono nella superClasse
sono nella subClasse
--
Antonio Pelleriti
Brainbench Java Master: score 4.34,
higher than 99% of all previous test takers.

SCUSATE!!!!!!!!!!!!!!!!!!!!!
mi sono accorto di un errore madornale, il codice corretto(che non dà il 
risultato sperato) era:
public class Pippo(){
   public void Pippo(){
   }
   public void initialize(){
     loadConf();
   }
   public void loadConf(){
     System.out.println("Sono nella superClasse");
   }
}
public class Paperoga() extend Pippo{
   public void Paperoga(){
   }
   public void initialize(){
     super.initialize();
     ^^^^^^^^^^^^^^^^^ PRIMA AVEVO SCRITTO UNA CAZZATA :-(((
                       QUESTO E' LA CHIAMATA GIUSTA :-)))
                       CI CREDO CHE TI FUNZIONAVA
     loadConf();
   }
   public void loadConf(){
     System.out.println("Sono nella subClasse");
   }
}
TX
Roberto beccaceci
rob...@ANTISPAMbeccaceci.it

 
Che visibilità hanno i metodi loadConf ??
public in entrambe le classi ???
Ho notato (come specificato nell mail che apre il tread) che cambiando 
la visibilità dei metodi cambia anche il  risultato....
-----------------------------------
se metto i due loadConf a private mi ritorna l'output giusto:
[OUTPUT]
Sono nella superClasse
Sono nella subClasse
-------------------------------------
se li metto tutte e due a protected:
[OUTPUT]
Sono nella subClasse
Sono nella subClasse
-------------------------------------
se metto il supermetodo a private ed il sub a protected mi ritorna:
[OUTPUT]
Sono nella superClasse
Sono nella subClasse
TX
Roberto Beccaceci
rob...@ANTISPAMbeccaceci.it

il motivo dipende dal fatto che Java
lavora con lo smistamento (binding) dinamico dei metodi
che č ha come base la redifinizione dei metodi.
Infatti run-time initialize() viene chiamato su Paperoga
che estende Pippo. Chiamando loadConf java viene
eseguito il loadConf "piů aggiornato" cioč il secondo.
ciao, Daniele.

 eseguito il loadConf "più aggiornato" cioè il secondo.
forse mi è sfuggito qualche concetto in quest'ultima frase
TX
Roberto

 forse mi è sfuggito qualche concetto in quest'ultima frase
cioè cerca di eseguire il metodo più aggiornato (o specializzato
chiamalo come vuoi) insomma quello più in basso nella
gerarchia di ereditarietà in caso di overriding.



il messaggio initialize() e' stato passato a Pippo che logicamente
non e' ingrado di rispondere con il metodo loadConf() di Paperoga
quindi rispondera' con il suo proprio metodo, quindi non credo che
Daniele Belli abbia ragione.
 
-- 
"Il soggetto va prima del pregiudicato, poi la congiuntivite
 e dopo la condizionale" - Francesco Totti

 Quando lancio Paperoga.initialize()
ma initialize() e' un metodo di istanza... e' corretto 
che una classe lanci un messaggio del genere? a quale oggetto
lo sta mandando?


 a=b;
Ma a e' un riferimento che punta ad una rappresentazione di un
oggetto di classe A che e' differente dalla rappresentazione
di un oggetto di classe B, c'e' sotto qualche cast implicito
(implicito poiche' B e' un "tipo" piu' ampio di A) quindi a 
diventa effettivamente un oggetto di classe B ed in questo
caso tutto l'esempio che hai fatto non starebbe piu in piedi ^_^
Spero di non aver detto una fesseria ^_^


 Daniele Belli abbia ragione.
Queste sono le basi del polimorfismo... mi sa che devi andare a studiare 
i concetti base dell'Object Orientation
uL

 Spero di non aver detto una fesseria ^_^
Purtroppo si ;)
uL

 Sono nella subClasse
io non so nemmeno come fa a funzionarti perche' a me nemmeno lo compila


 Purtroppo si ;)
perche'? dove il mio ragionamento e' sbagliato?


 i concetti base dell'Object Orientation
scusa mi era confuso ^_^


 
Perche' scrivendo:
a=b;
c'e' effettivamente un cast implicito (dato che si tratta di un upcast), ma del
reference...
Cioe' il reference memorizzato in b, una volta assegnato ad a viene
convertito al tipo (di reference) di a.
L'oggetto invece rimane com'era, cioe' un'istanza della classe B
(indicato da un reference ad oggetti della classe A, di cui B e' una
sottoclasse).
Quindi, quando si invoca un metodo usando il reference a, correttamente
viene invocato il metodo dell'oggetto che quel reference indica (cioe' il
metodo della classe B).
-- 
Lucio Benfante
Brainbench MVP for Java 1
http://www.brainbench.com
MyTranscript: 
http://www.brainbench.com/transcript.jsp?pid=167064

 metodo della classe B).
IMHO non si potrebbe semplicemente dire che facendo a=b
viene copiato il puntatore di b in a (cioè da quel momento a e b
puntano allo stesso indirizzo di memoria) dopodichè invocando
messaggi su a (*poichè c'è il binding dinamico*) i metodi che vengono
richiamati sono quelli per cui fa riferimento la refernce (e cioè per un
oggetto b)?
Magari è la stessa pappa ma rigirata? ;)
ciao


 dell'oggetto che quel reference indica (cioe' il metodo della classe B).
Poiche' con il binding dinamico ci si accorge che a sta puntando ad un
oggetto di classe B (che ha sostituito magari il metodo ereditato dalla
classe A che e' stato invocato) verra' usato il metodo ridefinito in B
(polimorfismo). Ma se invocassi su a un metodo che e' solo presente in B e
che non e' stato ereditato da A allora il compilatore mi darebbe errore
(cioe' ancora prima del run-time), vero?... sperando di averci azzeccato
^_^


 pappa ma rigirata? ;)
si... e' la stessa cosa


 cose ^_^).
Il concetto che ti manca e' la distinzione tra tipo statico e tipo 
dinamico (di una variabile). Data per buona la definizione di tipo :), il 
primo e' il tipo visto a compiletime, il secondo e' il tipo che l'ambiente 
runtime associa ad una certa variabile a, appunto, runtime.
Il tipo statico e' quello con cui sei familiare, a-la-Pascal per 
intenderci, ed e' l'unica cosa che determina la semantica dell'operatore di 
assegnamento e la correttezza di un'espressione che ne fa uso. 
In molti linguaggi imperativi, la distinzione non serve perche' tipo 
statico e dinamico coincidono.
Ad esempio, se in un linguaggio pascal-like scrivi begin a: integer; a = 
'c'; end; il compilatore s'incavola perche' il tipo di a e' "intero" e stai 
cercando di assegnarli un valore il cui tipo e' "carattere". Un 
assegnamento e' corretto se (1) i tipi delle espressioni a destra e 
sinistra sono identici (piu' altre cose, tipo il fatto che l'espressione a 
sinistra dev'essere "assegnabile", quello che in C si chiama lvalue).
Nei linguaggi OO, grazie ad un'estensione della semantica dell'operatore di 
assegnamento per quanto riguarda i tipi, e' possibile (in soldoni) 
assengare un'istanza di classe derivata ad un riferimento il cui tipo 
statico e' una sua classe base. E' cioe' legale scrivere cose del tipo Base 
b = new Derivata() (se e solo se Derivata estende Base). Ovviamente Base e 
Derivata sono tipi diversi (e quindi (1) e' violata) ma _siccome sono in 
quella relazione di ereditarieta'_) l'assegnamento e' corretto.
Ora, il tipo statico della variabile "b", sopra, e' "Base": che implica che 
il compilatore considerera' corretti solo usi di "b" come "Base" (ad 
esempio, se si invoca b.metodo(), metodo() dev'essere dichiarato da Base).
A runtime, pero', il supporto runtime registra il fatto che l'oggetto 
riferito da "b" e' in effetti di classe Derivata: il suo tipo dinamico e' 
"Derivata"; e usa questo fatto, ad esempio, per risolvere overrides di 
metodi o membri in generale (che e' a dire, se anche Derivata definisce 
metodo(), b.metodo() provochera' l'esecuzione del metodo()di Derivata, e 
non di Base), e in generale tutte le operazioni per cui lo specifico 
linguaggio prevede "late binding".
Nota che in Java una variabile il cui tipo e' dichiarato <classe X> ha 
sempre un solo tipo statico (classe X), ma puo' avere parecchi tipi 
dinamici (al minimo 2): la classe che estende (al minimo, Object), tutte le 
classi nella catena di estensione sopra X, tutte le classi nella catena di 
estensione tra X e l'eventuale classe derivata che e' stata specificata nel 
suo assegnamento con new(), piu' tutte le interfacce che implementa, 
eccetera.
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

 specifico linguaggio prevede "late binding".
ok ^_^
mi sembra di aver detto la stessa cosa nel messaggio a cui hai risposto,
tu pero' l'hai detta in maniera piu' precisa.


 tu pero' l'hai detta in maniera piu' precisa.
Puo' essere - il problema delle cose dette imprecisamente e' che non si 
capisce prescisamente cosa dicano. :-)
In particolare "referenzia solo la porzione che B eredita da A" poteva 
suggerire al lettore sprovveduto che l'oggetto sia in qualche modo 
"amputato" o che l'oggetto referenziato non sia sempre lo stesso.


 "amputato" o che l'oggetto referenziato non sia sempre lo stesso.
vabbe' io volevo dire che l'oggetto referenziato e' sempre lo stesso...
se non e' cosi' allora non ho capito niente, dimmelo che inizio di nuovo
a studiare dalla prima pagina ^_^


 a studiare dalla prima pagina ^_^
E cosi'. :)
