PDA

View Full Version : [JAVA] per veri esperti...


carMAN
20-04-2006, 13:42
Secondo voi si può fare qualcosa del genere?

Class Padre
{
Public Padre()
{
Figlio f = new Figlio();
}
}

Class Figlio
{
Private Object chiamante;

public Figlio()
{
This.chiamante = {un riferimento al Padre che ha creato il figlio}
}

}

non è possibile cambiare la firma del costruttore del figlio.
Grazie per l'aiuto
ciao

andbin
20-04-2006, 14:01
Secondo voi si può fare qualcosa del genere?

Class Padre
{
Public Padre()
{
Figlio f = new Figlio();
}
}

Class Figlio
{
Private Object chiamante;

public Figlio()
{
This.chiamante = {un riferimento al Padre che ha creato il figlio}
}

}

non è possibile cambiare la firma del costruttore del figlio.No, così non è possibile. Se ci pensi un attimo, un oggetto Figlio potrebbe essere creato in qualunque altro modo e in qualunque altro punto!

La firma del costruttore di Figlio dici che non la puoi cambiare. O non la vuoi cambiare?? Non puoi mettere magari un secondo costruttore in overload di Figlio che prenda come parametro un Padre?

cisc
20-04-2006, 14:03
concordo con andbin, al limite puoi rendere Figlio una inner class non statica di Padre, e riferirti all'oggetto padre in questione come Padre.this

andbin
20-04-2006, 14:12
al limite puoi rendere Figlio una inner class non statica di Padre, e riferirti all'oggetto padre in questione come Padre.thisconcordo con cisc. ;)
Io in effetti non l'ho proposto perché non so come e cosa devi fare di preciso ma una inner class non static potrebbe essere l'ideale.

carMAN
20-04-2006, 14:14
I padri di figlio sono moltissimi (molte classi diverse).
Praticamente ho necessità che il figlio conosca il padre che lo ha generato.

Con la reflection non si può fare nulla?

cisc
20-04-2006, 14:30
aspetta...i padri di figlio sono moltissimi..in che senso...dal codice che hai scritto sta cosa sembra impossibile..

fek
20-04-2006, 14:32
class A
{
public A()
{
B b = new B(this);
}
}

class B
{
private Object parent;

public B(Object parent)
{
this.parent = parent;
}
}

carMAN
20-04-2006, 14:34
class A
{
public A()
{
B b = new B(this);
}
}

class B
{
private Object parent;

public B(Object parent)
{
this.parent = parent;
}
}



La firma del figlio (B) non può essere cambiata.
Grazie per l'aiuto.

fek
20-04-2006, 14:45
La firma del figlio (B) non può essere cambiata.
Grazie per l'aiuto.

Perche'? Non hai accesso al codice di B?

carMAN
20-04-2006, 14:50
aspetta...i padri di figlio sono moltissimi..in che senso...dal codice che hai scritto sta cosa sembra impossibile..

Praticamente ci sono tante classi che instanziano un oggetto di tipo figlio

carMAN
20-04-2006, 14:54
Perche'? Non hai accesso al codice di B?

si, ma essendo il progetto molto grosso, con posso cambiare tutto il codice che ho già scritto

fek
20-04-2006, 15:02
si, ma essendo il progetto molto grosso, con posso cambiare tutto il codice che ho già scritto

Se usi Eclipse (o equivalente), apri il menu di refactor, scegli "Change signature", cambia la signature del costruttore e passa this come parametro di default. Eclipse aggiornera' tutti i riferimenti da solo.

Se non usi Eclipse (o equivalente), usa Eclipse.

cisc
20-04-2006, 15:07
Praticamente ci sono tante classi che instanziano un oggetto di tipo figlio

si, quindi ogni istanza di figlio ha un padre, e puoi usare tranquillamente le inner class

andbin
20-04-2006, 15:11
Praticamente ci sono tante classi che instanziano un oggetto di tipo figlioScusa, fammi capire. Hai una cosa del tipo:
Class Padre1 {
Public Padre1() {
Figlio f = new Figlio();
}
}

Class Padre2 {
Public Padre2() {
Figlio f = new Figlio();
}
}

ecc.... :confused: :confused:

carMAN
20-04-2006, 15:16
Scusa, fammi capire. Hai una cosa del tipo:
Class Padre1 {
Public Padre1() {
Figlio f = new Figlio();
}
}

Class Padre2 {
Public Padre2() {
Figlio f = new Figlio();
}
}

ecc.... :confused: :confused:


esatto!!!

e il figlio deve sapere quale padre lo ha chiamato.

cisc
20-04-2006, 15:16
Scusa, fammi capire. Hai una cosa del tipo:
Class Padre1 {
Public Padre1() {
Figlio f = new Figlio();
}
}

Class Padre2 {
Public Padre2() {
Figlio f = new Figlio();
}
}

ecc.... :confused: :confused:

vabbè, se la situazione è questa, l'unica soluzione decente mi sembra sia quella di fek..

andbin
20-04-2006, 15:22
esatto!!!Allora le inner class dimenticale perché non sono utilizzabili. L'unica possibilità è quella di aggiungere un parametro (Padre) al costruttore di Figlio e modificare in tutti i punti l'istanziazione dell'oggetto Figlio.

carMAN
20-04-2006, 15:41
Se usi Eclipse (o equivalente), apri il menu di refactor, scegli "Change signature", cambia la signature del costruttore e passa this come parametro di default. Eclipse aggiornera' tutti i riferimenti da solo.

Se non usi Eclipse (o equivalente), usa Eclipse.

Possibile!!!!
Con la reflection non si può fare nulla?

fek
20-04-2006, 16:10
Possibile!!!!
Con la reflection non si può fare nulla?

Nulla di cui sia lecito parlare in pubblica e di piu' non domandare :D

No, puoi solo interrogare i metadati di una classe, non la sua storia. L'unica soluzione e' cambiare il costruttore e farti aiutare da un tool di refactoring. Ci vuole davvero meno che scrivere questo post.

carMAN
20-04-2006, 16:22
.... Ci vuole davvero meno che scrivere questo post.

sicuramente...
ma è più per curiosità ...diciamo un esercizio teorico...... che mi sa purtroppo rimanere inrisolto....

ciao ciao

PGI-Bis
20-04-2006, 16:24
La caratteristica che vorresti usare non è supportata dal linguaggio di programmazione Java. Il che impedisce al package reflect di essere d'aiuto.

La tua richiesta non è affatto bizzarra, anzi. Si scontra tuttavia con il minimo sindacale del "messaggio": gli oggetti ricevono messaggi. Da chi non lo sanno.

Nel caso dei costruttori Java, il chi neppure c'è: non è Padre che invoca il costruttore di Figlio. E' new che esegue la procedura di inizializzazione prevista dal costruttore Figlio(), facendola subire ad un'istanza di Figlio. Vale a dire che il costruttore non è neppure un membro.

Non c'è una soluzione diretta che ti consenta di introdurre l'effetto desiderato senza manipolare il codice della classe Figlio e della classe Padre o delle classi in cui siano generati degli oggetti Padre o Figlio.

La soluzione che astrattamente preferirei io è quella di realizzare la metafora della comunicazione che è poi quella che consente di toccare con mano i benefici dell'orientamento agli oggetti. Tuttavia è un approccio è più simile all'invasione della Normandia che al breve e più che corretto tocco di pennello suggerito da Fek.

Credo anch'io che convenga fare un refactoring.

carMAN
21-04-2006, 08:19
Grazie, finalmente una risposta chiarificatrice.Ma mi sovviene un dubbio...
Come funziona allora la propagazione dell'eccezione? Mi spiego meglio....


Class Padre1 {
Public Padre1() {
try{
Figlio f = new Figlio();
} catch(Exception e) {System.out.println("Eccezione catturata da Padre1");}
}
}

Class Padre2 {
Public Padre2() {
try{
Figlio f = new Figlio();
} catch(Exception e) {System.out.println("Eccezione catturata da Padre2");}
}
}

Class Figlio{
Public Figlio() throws Exception {
Object oggetto=null;
if (oggetto == null) throw new Exception("Prova di Propagazione Eccezione");
}
}



In questo modo viene mantenuta una traccia di chi istanzia Figlio? Altrimenti la propagazione delle eccezioni non potrebbe funzionare.

dnarod
21-04-2006, 08:57
Se non usi Eclipse (o equivalente), usa Eclipse.

lol :)

PGI-Bis
21-04-2006, 13:05
Circa la propagazione delle eccezioni direi che sei nel giusto. D'altronde che il programma deva tener traccia della successione di invocazioni (dal metodo X al metodo Y, dal costruttore X al costruttore Y o al metodo Z e via discorrendo) non è cosa necessaria alla sola gestione delle eccezioni: se in un metodo è invocato un altro metodo, quando il secondo terminerà il suo compito il controllo tornerà al primo.

Il meccanismo non è tuttavia sfruttabile. Funziona al contrario di quanto servirebbe a te: dal figlio torna al padre, mentre a te interesserebbe qualcosa che dal padre riversa informazioni nel figlio affinchè questi possa conservarle.

Ma, ancora prima di questo, l'impedimento fondamentale risiede nel linguaggio. Circa la gestione delle eccezioni è detto cosa deve capitare, quando deve capitare e chi sia coinvolto. Il "come" è lasciato nelle mani della concreta implementazione del linguaggio. Non essendo fissato nelle regole del linguaggio il "come", non è possibile avvalersi del meccanismo che conserva i rapporti chiamato/chiamante, sebbene certamente uno esista.

fek
21-04-2006, 13:39
In questo modo viene mantenuta una traccia di chi istanzia Figlio? Altrimenti la propagazione delle eccezioni non potrebbe funzionare.

La traccia e' tenuta nel callstack che memorizza tutta la catena di chiamate per arrivare al metodo correntemente attivo. Da programma non si ha acesso al call stack, ed e' giusto che sia cosi'. Stai cercando di abusare del linguaggio per fare qualcosa di estremamente semplice e la cui soluzione e' altrettanto semplice.

Se pensi che cercare di abusare del linguaggio cosi' piuttosto che semplicemente cambiare il costruttore ti fara' risparmiare tempo sei in errore: te ne fara' perdere, e molto. Cambia il costruttore e passa ad altro.