Newsgroup: it.comp.java
Titolo: Domanda per esperti

Qualcuno mi sa spiegare perchè il seguente codice si comporta in questo
modo:
class Base
{
    public Base()
    {
        show();
    }
    public void show()
    {
        System.out.println("Base");
    }
}
class Estesa extends Base
{
    public show()
    {
        System.out.println("Estesa");
    }
}
Estesa a=new Estesa();
ed il programma stampa estesa  invece di stampare Base!!!!  Esiste un
modo per superare questo comportamento alquanto strano ed obbligare il
codice a richiamare la propria funzione membro all'iinterno dei
costruttori  che può essere fonte di errori  difficilmente
rintracciabili nei programmi?
Grazie per eventuali risposte. Angelo

Grazie per eventuali risposte. Angelo
Il comportamento non e' strano :), ma corretto: anche nel costruttore, dopo 
l'esecuzione del costruttore della classe base super() (nel tuo caso chiamato 
implicitament), l'oggetto e' costruito e quindi i metodi invocati sono quelli 
del tipo dinamico.
Usa super.show() se vuoi invocare esplicitamente il metodo della classe base.
-- 
God is Real, unless declared Integer.
ObjectZone - 
http://space.tin.it/computer/csadun/

 del tipo dinamico.
Grazie per la risposta (seguo attentamente tutti i tuoi interventi sul news) ma
il comportamento non č corretto (almeno confrontandolo al comportamento del c++
)che blocca (giustamente) il meccanisnmo delle chiamate virtuali all'interno di
costruttori e distruttori. A prescindere dal problema in se volevo sapere se
esiste una qualche tecinca che obblighi il il codice ad eseguire il metodo della
propria classe bloccando in pratica il collegamento dinamico (anche scrivendo
this.show() viene comunque richiamato il metodo della classe Estesa (e questo mi
sembra ancora piů strano) .
Ciao Angelo

metodo della classe Estesa (e questo mi sembra ancora piů strano) .
Se capisco bene (non sono sicuro) e' sufficiente dichiarare il metodo
private. Ad esempio in: 
public class Base {
 public Base() { m(); }
 private void m() {  System.out.println("BASE"); }
}
public class Derivata extends Base {
 private void m() {  System.out.println("DERIVATA"); }
 public Derivata() { m(); }
 public static void main(String args[]) {  Derivata d=new Derivata(); }
}
Il risultato e' 
BASE
DERIVATA


Non mi sembra un comportamento strano: quando la sottoclasse invoca il
costruttore viene invocato quello della superclasse, questo invoca il metodo
show(), ma essendo il tutto avviato dalla sottoclasse il metodo e "coperto"
dall'analogo della sottoclasse!
In pratica, ogni volta che viene invocato un metodo di una sottoclasse Java
cerca sempre prima un riferimento al metodo nella classe dell'oggetto
chiamante e poi nella superclasse..
Ciao!

 DERIVATA
Hai ragione , in effetti il comportamento non è scorretto ma sono
semplicemente le specifiche che sembrerebbero discutibili. Oltretutto
questo meccanismo provoca spesso degli errori  (specialmente utilizzando le
swing che sono un intreccio di interfaccie , metodi e classi astratte,
metodi factory etc etc ) che sono difficlmente individuabili se non lo si
comprende  bene.
E comunque grazie per  il chiarimento, volevo sentire il parere di un
esperto al riguardo
Ciao Angelo

Esteban wrote:
Il problema è il seguente (vedi anche la risposta di Cristiano Sadun): se
estendi una classe qualunque e ridefinisci un metodo (al limite anche senza
saperlo visto che la gerarchia  è molto profonda e la probabilità di scrivere
un setX() uguale a quello di una superclasse non è poi così bassa) e in tale
metodo utilizzi degli oggetti che sono membri della tua classe estesa e che
(credi )aver inizializzato nel costruttore ti ritrovi con delle eccezioni
inspiegabili perchè 'qualcuno' ha chiamato il tuo metodo prima che la classe
sia stata completamente costruita.  Questo mi sembra alquanto strano come
comportamento.

se non lo si comprende  bene.
Ecco, questo e' un punto importante. La disponibilita' di uno strumento
di modellazione in piu' rispetto a C++ (le interfacce, appunto) rende il
linguaggio potente nella modellazione, ma come dici richiede di aver
compreso molto bene non solo la teoria, ma la pragmatica del loro uso. 
Dopo un po', "leggendo" librerie Java, cominci ad aver la sensazione di
averle scritte tu, tanto fluida e' la traduzione dalle comuni strategie
di design al codice.. Swing comprese, pero' bisogna farci un minimo la
mano. Con C++ - puo' essere, ovviamente, per limite mio ;-) - mi e'
raramente successo. 
LOL e in effetti il problema e' comune: l'altro ieri ho passato il primo
draft del design di un sistema che stiamo costruendo al coordinatore
dello sviluppo, che viene anche lui dal C++... e abbiamo passato due
giorni a chiarire i perche' e i percome. Non ho piu' voce. :) 



Puoi provare due cose :
1 mettere nel costruttore di Estesa come primo (e unico) comando
        super();
2 mettere nel costruttore di Estesa come primo (e eventualmente unico)
comando
        super.show()
Uno dei due dovrebbe funzionare.
Non so se sono stato utile, spero di si
Fammi sapere.
Ciao,
   Massimo