Newsgroup: it.comp.java
Titolo: Ereditarietà e tipi variabili

Come mai con il seguente codice:
class A {
    public Object obj;
    public A() {
        obj = null;
    }
    public void stampa() {
        System.out.println(obj);
    }
}
class B extends A {
    public String obj;
    public B() {
        obj = new String("Ciao");
    }
}
class prova {
    public static void main(String args[]) {
        B classe_B = new B();
        classe_B.stampa();
        System.out.println(classe_B.obj);
    }
}
ottengo in output prima 'null' poi 'Ciao'?
Esistono un'istanza della classe A ed una della classe B?

 ha scritto nel messaggio
news:FQJDa.63622$lK4.1...@twister1.libero.it...

Perchè, quando esegui l'istruzione:
    B classe_B = new B();
ti "parte" prima il costruttore della superlcasse, il quale
assegna null a obj della superclasse, poi ti "parte" il costruttore
della sottoclasse, che assegna "Ciao" al suo obj Stringa.
Successivamente, con l'istruzione
   classe_B.stampa();
ti parte il metodo della superlcasse A, visto che
stampa non l'hai ridefinita in B, e quel metodo
stampa null, perchè fa riferimento al "suo" obj
Infine, l'istruzione
     System.out.println(classe_B.obj);
stamerà il valore della variabile di B, che invece
è "Ciao"
               IL SANTO
p.s.
classe_B.obj  (cioè...ciao)

 
Il risultato e' quello, pero' la successione di chiamata dei costruttori
non e' esattamente quella che tu hai descritto:
1. viene istanziato un oggetto della classe B (allocazione della memoria e
impostazione dei vari campi di istanza al valore di default per il loro
tipo)
2. viene eseguito il costruttore di B
3. all'inizio del costruttore di B viene chiamato il costruttore senza
parametri della superclasse di B (A) (chiamata aggiunta dal compilatore,
dato che non ne viene e' presente una esplicita).
4. all'inizio del costruttore di A viene chiamato il costruttore senza
parametri (l'unico :-)) della superclasse di A (Object), per lo stesso
motivo di prima.
5. terminata l'esecuzione del costruttore di Object si ritorna al
costruttore di A
6. terminato il costruttore di A si ritorna al costruttore di B
7. Al suo termine, l'oggetto e' costruito
Inoltre (ma in questo caso non ce ne sono), al ritorno dall'esecuzione di
ogni costruttore della superclasse, vengono eseguiti gli inizializzatori
espliciti dei campi di istanza e tutti i blocchi di inizializzazione.
In ogni caso, non esistono due oggetti (un'istanza di A e una di B), ma
solo uno, istanza di B.
...giusto per spirito di precisione ;-)
-- 
Lucio Benfante
Brainbench MVP for Java 1
http://www.brainbench.com
MyTranscript: 
http://www.brainbench.com/transcript.jsp?pid=167064

 solo uno, istanza di B.
... perň esistono 2 oggetti obj diversi tra loro, giusto?
Il mio intento era di ridefinire un oggetto della classe padre (Object obj)
con un oggetto derivato (String obj), per poi usare l'oggetto derivato nella
sottoclasse, che "raffinava" la classe padre.
Il tutto doveva essere realizzato in una classe BinarySearchTree che
implementa un albero binario di ricerca, derivata dalla classe Binary che
implementa un normale albero binario.
L'oggetto memorizzato in BinaryTree doveva essere un generico Object, mentre
quello nell'albero di ricerca doveva implementare l'interfaccia Comparable.
La classe BinarySearchTree perň chiama metodi della classe BinaryTree, che
quindi vedevano un oggetto diverso.
Alla fine ho risolto tutto non ridefinendo l'oggetto nella classe derivata
BinarySearchTree e usando il cast (Object) obj nei metodi che scrivono obj e
accettano come parametro un oggetto Comparable.
Esiste per caso qualche soluzione piů elegante?

 ...giusto per spirito di precisione ;-)
Per "spirito di precisone", dove?
                 IL SANTO
p.s
Famme ride ;)

 Esiste per caso qualche soluzione piů elegante?
Non mi e' molto chiaro. Il cast a Object non e' necessario, dato che e' un
upcast e tutte le classi derivano da Object. Quindi nella classe
BinaryTree non dovrebbe esserci nessuna modifica (dato che e' stata
costruita usando solo le caratteristiche degli Object): i suoi metodi
ricevono ed utilizzano solo Object (e quindi eventualmente anche dei
Comparable, ma non ne utilizzano le funzionalita' specifiche).
La classe BinarySearchTree invece utilizzera' dei Comparable, facendo il
cast a Comparable di obj nel momento i cui servono quelle funzionalita'. I
suoi metodi, in generale, riceveranno e utilizzeranno dei Comparable.
Da quello che hai detto, ho l'impressione che tu abbia definito nella classe
BinaryTree metodi che invece andrebbero in BinarySearchTree, o comunque
di cui bisognerebbe fare l'overloading in quest'ultima classe.
Soprattutto, nella classe BinaryTree non dovresti avere nelle signature
dei metodi dei Comparable, dato che (hai detto tu) quella classe non
dipende dalle funzionalita' di quell'interfaccia.
