D4rkAng3l
26-01-2009, 19:21
L'esame di linguaggi di programmazione si avvicina sempre di più (manca una settimana circa)...vi posto quà 2 domande trovate su un vecchio compito...mi dite se vanno bene o se ho sbagliato qualcosa o sono stato incompleto?
1) Che cos'è un effetto collaterale? Descrivere le modalità di occorrenza degli effetti collaterali in Java presentando esempi e mostrare cosa avviene all'interno della memoria
Si dice che un metodo causa un effetto collaterale quando esso modifica una variabile locale o globale al di fuori del proprio scope (cioè se per qualche motivo il metodo riesce a modificare una variabile fuori dal suo campo di visibilità).
In Java si può verificarsi un effetto collaterale SOLO se il parametro di un metodo è un oggetto modificabile.
Un effetto collaterale non è per forza una situazione di errore o un problema, se gestito correttamente a volte può essere l'unica soluzione per risolvere particolari tipi di situazioni come ad esempio la creazione di una lista concatenata di interi in Java che può essere implementata mediante due classi, una classe NodoInt che rappresenta i singoli nodi della lista ed un'altra classe ListaDiInteri che rappresenta la lista in questione con una cosa del tipo:
/** Classe che rappresenta e gestisce singoli nodi di una lista concatenata; Gli oggetti sono MUTABILI */
public class NodoInt{
private int valore; // Valore di tipo intero contenuto nel nodo (è il campo informazione del nodo)
private NodoInt successivo; // Contiene il riferimento ad un oggetto di tipo NodoInt che contiene l'elemento successivo
/** COSTRUTTORE :crea un nodo il cui valore è quello del parametro e che non è concatenato ad alcun altro nodo */
public NodoInt(int n){
valore = n; // Nel campo valore del nuovo nodo creato viene messo il valore del parametro
successivo = null; // Nel campo successivo viene messo il valore null: il nuovo nodo non punta a niente
}
/** Accede in lettura al valore del nodo oggetto ricevente */
public int getValore(){
return valore; // Ritorna il valore contenuto nel nodo oggetto ricevente
}
/** Accede in lettura al riferimento al nodo che segue il nodo oggetto ricevente. *NB: Espone l'oggetto ricevente a
possibili effetti collaterali */
public NodoInt getSuccessivo(){
return successivo;
}
/** Configura l'oggetto ricevente in modo tale da avere il parametro come successore. *NB: Modifica l'oggetto ricevente */
public void setSuccessivo(NodoInt altro){
this.successivo = altro;
}
........................
........................
........................
e
/** Classe che rappresenta e gestisce una lista concatenata di nodi che contengono valori interi; Gli oggetti sono MUTABILI */
public class ListaDiInteri{
private NodoInt N; // Primo nodo della lista
/** COSTRUTTORE: Crea un nuovo oggetto ListaDiInteri che inizialmente è una lista vuota*/
public ListaDiInteri(){
N = null; // Il primo nodo è inizialmente un elemento nullo
}
/** Se il nodo parametro non ha successori lo aggiunge in testa alla lista alla lista, altrimenti crea un nodo il cui
valore coincide con quello del parametro e lo aggiunge in testa alla lista. *NB: Modifica l'oggetto ricevente */
public void aggiungiInTesta(NodoInt altro){
NodoInt T = new NodoInt(altro.getValore()); // Costruisce un nuovo nodo T avente il valore di altro
T.setSuccessivo(N); // Il nodo T è diventatola la nuova testa della lista e punta alla vecchia testa
N = T;
}
/** Crea un nodo il cui valore coincide con il parametro di tipo intero e lo aggiunge in testa alla lista.
*NB: Modifica l'oggetto ricevente */
public void aggiungiInTesta(int n){
NodoInt T = new NodoInt(n);
T.setSuccessivo(N);
N = T;
}
....................
....................
....................
Appare chiaro che gli oggetti NodoInt sono oggetti modificabili in quanto il metodo setSuccessivo() modifica il campo successivo dell'oggetto ricevente per aggiungere un nodo alla lista sfruttando appunto un effetto collaterale.
Magari qualcuno mi fà un'esempio di un effetto collaterale (anche pericoloso) più spicciolo...se mi fà questa domanda all'esame vorrei evitare di impelagarmi a parlare di liste concatenate sul compito :eek:
2) Descrivere le due tecniche per VALORE, per RIFERIMENTO e per VALORE-RISULTATO dei parametri attuali ai parametri formali. Mostrare anche mediante esempi in cosa differiscono
Questo può essere fatto non per forza in Java...io mi troverei meglio a parlare in simil-C per spiegare cosa sono :D
Quando invoco una routine posso passare i parametri in vari modi.
Quando viene invocata una routine con passaggio dei parametri per valori significa che il valore dei parametri attuali viene copiato nei parametri formali sui quali la routine andrà ad operare ed i parametri attuali non saranno in alcun modo modificati dalla computazione della routine.
Esempio passaggio per valore:
int main(){
int a[3] = {1,2,3}
test(a[1], a[2]);
return 0;
}
void test(int x, int y){
x = 0;
y++;
}
In questo caso vengono passati alla routine due parametri formali x ed y contenenti dellecopie dei valori in a[1] ed a[2] (2 e 3). La routine poi rende x pari a 0 ed incremente y di 1, quindi y diventa 4. I valori contenenti nei parametri attuali della routine invocante non vengono modificati. Quando la routine test() termina la propria esecuzione i valori di x ed y sono deallocati.
Se invece il linguaggio usasse il passaggio dei parametri PER RIFERIMENTO sarebbero stati passati gli indirizzi dei parametri attuali che sarebbero stati modificati (è un effetto collaterale?)
*NB: In C non esiste il passaggio per riferimento in quanto è pervisto dal linguaggio solo il passaggio per valore, tuttavia può essere solo simulato il passaggio di riferimento passando i puntatori dei parametri attuali
Se un linguaggio invece implementa il passagio dei parametri per VALORE-RISULTATO succede che:
i parametri attuali sono copiati ne parametri formali per VALORE.
La routine viene eseguita ed alla fine della routine i parametri formali vengono ricopiati nei parametri attuali.
Quindi facendo riferimento all'esempio precedente:
La routine riceve una copia dei valori a[1] ed a[2] dentro x ed y
--> x = 2 ed y=3
Poi viene eseguita la routine: x=0 ed y=4
Ed infine questi valori vengono ricopiati nei parametri attuali (quindi la semantica è diversa: in entrata il passaggio dei dati alla routine è per valore, in uscita è per riferimento) e l'array iniziale è diventato: [1,0,4]
Su quest'ultima cosa non ne sono sicurissimo però...
Grazie
Andrea
1) Che cos'è un effetto collaterale? Descrivere le modalità di occorrenza degli effetti collaterali in Java presentando esempi e mostrare cosa avviene all'interno della memoria
Si dice che un metodo causa un effetto collaterale quando esso modifica una variabile locale o globale al di fuori del proprio scope (cioè se per qualche motivo il metodo riesce a modificare una variabile fuori dal suo campo di visibilità).
In Java si può verificarsi un effetto collaterale SOLO se il parametro di un metodo è un oggetto modificabile.
Un effetto collaterale non è per forza una situazione di errore o un problema, se gestito correttamente a volte può essere l'unica soluzione per risolvere particolari tipi di situazioni come ad esempio la creazione di una lista concatenata di interi in Java che può essere implementata mediante due classi, una classe NodoInt che rappresenta i singoli nodi della lista ed un'altra classe ListaDiInteri che rappresenta la lista in questione con una cosa del tipo:
/** Classe che rappresenta e gestisce singoli nodi di una lista concatenata; Gli oggetti sono MUTABILI */
public class NodoInt{
private int valore; // Valore di tipo intero contenuto nel nodo (è il campo informazione del nodo)
private NodoInt successivo; // Contiene il riferimento ad un oggetto di tipo NodoInt che contiene l'elemento successivo
/** COSTRUTTORE :crea un nodo il cui valore è quello del parametro e che non è concatenato ad alcun altro nodo */
public NodoInt(int n){
valore = n; // Nel campo valore del nuovo nodo creato viene messo il valore del parametro
successivo = null; // Nel campo successivo viene messo il valore null: il nuovo nodo non punta a niente
}
/** Accede in lettura al valore del nodo oggetto ricevente */
public int getValore(){
return valore; // Ritorna il valore contenuto nel nodo oggetto ricevente
}
/** Accede in lettura al riferimento al nodo che segue il nodo oggetto ricevente. *NB: Espone l'oggetto ricevente a
possibili effetti collaterali */
public NodoInt getSuccessivo(){
return successivo;
}
/** Configura l'oggetto ricevente in modo tale da avere il parametro come successore. *NB: Modifica l'oggetto ricevente */
public void setSuccessivo(NodoInt altro){
this.successivo = altro;
}
........................
........................
........................
e
/** Classe che rappresenta e gestisce una lista concatenata di nodi che contengono valori interi; Gli oggetti sono MUTABILI */
public class ListaDiInteri{
private NodoInt N; // Primo nodo della lista
/** COSTRUTTORE: Crea un nuovo oggetto ListaDiInteri che inizialmente è una lista vuota*/
public ListaDiInteri(){
N = null; // Il primo nodo è inizialmente un elemento nullo
}
/** Se il nodo parametro non ha successori lo aggiunge in testa alla lista alla lista, altrimenti crea un nodo il cui
valore coincide con quello del parametro e lo aggiunge in testa alla lista. *NB: Modifica l'oggetto ricevente */
public void aggiungiInTesta(NodoInt altro){
NodoInt T = new NodoInt(altro.getValore()); // Costruisce un nuovo nodo T avente il valore di altro
T.setSuccessivo(N); // Il nodo T è diventatola la nuova testa della lista e punta alla vecchia testa
N = T;
}
/** Crea un nodo il cui valore coincide con il parametro di tipo intero e lo aggiunge in testa alla lista.
*NB: Modifica l'oggetto ricevente */
public void aggiungiInTesta(int n){
NodoInt T = new NodoInt(n);
T.setSuccessivo(N);
N = T;
}
....................
....................
....................
Appare chiaro che gli oggetti NodoInt sono oggetti modificabili in quanto il metodo setSuccessivo() modifica il campo successivo dell'oggetto ricevente per aggiungere un nodo alla lista sfruttando appunto un effetto collaterale.
Magari qualcuno mi fà un'esempio di un effetto collaterale (anche pericoloso) più spicciolo...se mi fà questa domanda all'esame vorrei evitare di impelagarmi a parlare di liste concatenate sul compito :eek:
2) Descrivere le due tecniche per VALORE, per RIFERIMENTO e per VALORE-RISULTATO dei parametri attuali ai parametri formali. Mostrare anche mediante esempi in cosa differiscono
Questo può essere fatto non per forza in Java...io mi troverei meglio a parlare in simil-C per spiegare cosa sono :D
Quando invoco una routine posso passare i parametri in vari modi.
Quando viene invocata una routine con passaggio dei parametri per valori significa che il valore dei parametri attuali viene copiato nei parametri formali sui quali la routine andrà ad operare ed i parametri attuali non saranno in alcun modo modificati dalla computazione della routine.
Esempio passaggio per valore:
int main(){
int a[3] = {1,2,3}
test(a[1], a[2]);
return 0;
}
void test(int x, int y){
x = 0;
y++;
}
In questo caso vengono passati alla routine due parametri formali x ed y contenenti dellecopie dei valori in a[1] ed a[2] (2 e 3). La routine poi rende x pari a 0 ed incremente y di 1, quindi y diventa 4. I valori contenenti nei parametri attuali della routine invocante non vengono modificati. Quando la routine test() termina la propria esecuzione i valori di x ed y sono deallocati.
Se invece il linguaggio usasse il passaggio dei parametri PER RIFERIMENTO sarebbero stati passati gli indirizzi dei parametri attuali che sarebbero stati modificati (è un effetto collaterale?)
*NB: In C non esiste il passaggio per riferimento in quanto è pervisto dal linguaggio solo il passaggio per valore, tuttavia può essere solo simulato il passaggio di riferimento passando i puntatori dei parametri attuali
Se un linguaggio invece implementa il passagio dei parametri per VALORE-RISULTATO succede che:
i parametri attuali sono copiati ne parametri formali per VALORE.
La routine viene eseguita ed alla fine della routine i parametri formali vengono ricopiati nei parametri attuali.
Quindi facendo riferimento all'esempio precedente:
La routine riceve una copia dei valori a[1] ed a[2] dentro x ed y
--> x = 2 ed y=3
Poi viene eseguita la routine: x=0 ed y=4
Ed infine questi valori vengono ricopiati nei parametri attuali (quindi la semantica è diversa: in entrata il passaggio dei dati alla routine è per valore, in uscita è per riferimento) e l'array iniziale è diventato: [1,0,4]
Su quest'ultima cosa non ne sono sicurissimo però...
Grazie
Andrea