|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
[Java] Chiarimento copia hard nel costruttore
mmm, la professoressa ha trattato il concetto di copia hard in Java...mi dite se ho capito bene o se mi sfugge qualcosa?
Faccio un esempio pratico: ho una classe chiamata Rettangolo che mi definisce dei rettangoli e delle operazioni su di essi: Codice:
public class Rettangolo{
public Punto Pbl, Ptr; // Le variabili di istanza
Pbl: il punto ineriore sinistro Ptr: il punto superiore destro in pratica definisco un rettangolo da 2 particolari dei suoi vertici diagonalmente opposti tra loro. Ovviamente per funzionare la classe rettangolo ha bisogno del tipo di datp Punto definito proprio nella classe Punto: Codice:
public class Punto{
private double x,y; // Sono le variabili di istanza che rappresentano le coordinate del punto
/** Costruttore di oggetti istanza della classe Punto date le sue coordinate
@param x di tipo double: l'ascissa del punto da creare
@param y di tipo double: l'ordinata del punto da creare */
public Punto(double x, double y){
this.x = x; // La variabile di istanza x dell'oggetto da creare è ugale al valore del parametro x passato al costruttore
this.y = y; // La variabile di istanza y dell'oggetto da creare è ugale al valore del parametro y passato al costruttore
}
(in entrambe le classi non inserisco tutti i metodi se no sarebbe lunghissimo) Se gli oggetti di tipo Punto non sono modificabili (per esempio non posso traslare un punto lungo l'asse x o y) allora per la classe Rettangolo potrò usare un costruttore banale come Codice:
public Retangolo(Punto P1, Punto P2){
this.Pbl = P1;
this.Ptr = P2;
}
Mettiamo ora caso che dentro la mia classe Punto ci voglio mettere due metodi: traslaLungoAsseX() e traslaLungoAsseY() che modificano l'oggetto punto cambiandone nel primo il valore dell'ascissa e nel secondo il valore dell'ordinata. A questo punto avrei che le variabili di istanza della classe rettangolo (Punto Pbl, Ptr) sono 2 OGGETTI MODIFICABILI e sono nella cacca perchè se nel main traslo un punto che è anche vertice di un rettangolo ne consegue che ho modificato anche il rettangolo che avevo precedentemente creato e ciò potrebbe essere disastroso...allora se le variabili di istanza della classe Rettangolo sono oggetti modificabili devo usare un costruttore che fà la COPIA HARD. Cioè io al costruttore gli passo due oggetti di tipo Punto P1 e P2 e lui invece di assegnare ai vertici Pbl e Ptr il riferimento a P1 e P2 ne fà prima una copia edattribuisce ai miei vertici la copia...così se qualcuno modifica i punti di partenza nel main non va a smerdare anche il rettangolo costruito. quindi avrò qualcosa del genere come nuovo costruttore sicuro: Codice:
public Rettangolo(Punto P1, Punto P2){
if(P1.getAscissa() < P2.getAscissa()){
if(P1.getOrdinata < P2.getOrdinata()){ // Se l'ascissa di P1 è minore dell'ascissa di P2 e se l'ordinata di P1 è minore dell'ordinata di P2
Pbl = new Punto(P1.getAscissa(), P1.getOrdinata());
Ptr = new Punto(P2.getAscissa(), P2.getOrdinata());
}
else{ // Se l'ascissa di P1 è minore dell'ascissa di P2 e se l'ordinata di P1 è maggiore dell'ordinata di P2
Pbl = new Punto(P1.getAscissa(), P2.getOrdinata());
Ptr = new Punto(P2.getAscissa(), P1.getOrdinata());
}
}
else{
if(P1.getOrdinata < P2.getOrdinata){ // Se l'ascissa di P1 è maggiore dell'ascissa di P2 e se l'ordinata di P1 è minore dell'ordinata di P2
Pbl = new Punto(P2.getAscissa, P1.getOrdinata);
Ptr = new Punto(P1.getAscissa, P2.getOrdinata):
}
else{ // Se l'ascissa di P1 è maggiore dell'ascissa di P2 e se l'ordinata di P1 è maggiore dell'ordinata di P2
Pbl = new Punto(P2.getAscissa(), P2.getOrdinata);
Ptr = new Punto(P1.getAscissa(), P1.getOrdinata);
}
}
E' correto come ragionamento? Grazie Andrea |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Mar 2005
Città: Morimondo city
Messaggi: 5491
|
non capisco la necessità di traslare i punti,se ti servono altre coordinate non puoi istanziare nuovi punti?
__________________
Khelidan |
|
|
|
|
|
#3 | |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Quote:
Cmq è corretto il mio ragionamento? |
|
|
|
|
|
|
#4 |
|
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Sì è corretto.
Ed il motivo è molto semplice: in Java, quando passi come parametri a dei metodi delle variabili non primitive (cioè gli oggetti) in realtà non stai passando l'oggetto vero e proprio ma solo una variabile reference "che punta" a quell'oggetto. Il che significa che se, dentro a un costruttore di una classe Rettangolo che prende in ingresso due reference a due oggetti Punto, fai così: Codice:
class Rettangolo
{
Punto p1; // reference ad un oggetto Punto
Punto p2;
...
public Rettangolo(Punto p1, Punto p2)
{
// copio la reference passata come parametro
// nella reference mantenuta da questa istanza di Rettangolo:
// entrambe le due distinte reference puntano allo stesso oggetto Punto
this.p1 = p1;
this.p2 = p2;
}
}
Se invece fai così: Codice:
class Rettangolo
{
Punto p1; // reference ad un oggetto Punto
Punto p2;
...
public Rettangolo(Punto p1, Punto p2)
{
// uso la reference passata come parametro per creare un nuovo
// oggetto Punto che poi "attacco" alla reference mantenuta da questa
// istanza di Rettangolo:
// le due distinte reference puntano a due diversi oggetti Punto
this.p1 = new Punto(p1.x(), p1.y());
this.p2 = new Punto(p2.x(), p2.y());
}
}
Ricordati sempre la differenza tra reference e oggetto in Java: Codice:
REFERENCE = OGGETTO Punto reference = new Punto(15, 200);
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
|
|
|
|
#5 |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Ok perfetto...vediamo se ho capito bene tutto il tuo ragionamento
Se per esempio volessi inserire nella classe Rettangolo un secondo costruttore che passatogli 4 parametri double x1,y1, x2,y2 che sono le coordinate dei due vertici diagonalmente opposti costruisce un rettangolo, quindi: Codice:
/** 2) Costruisce un oggetto di tipo Rettangolo date le coordinate di due suoi punti diagonalmente opposti.
@param x1 di tipo int: è l'ascissa del primo punto
@param y1 di tipo int: è l'ordinata del primo punto
@param x2 di tipo int: è l'ascissa del secondo punto
@param y2 di tipo int: è l'ordinata del secondo punto */
public Rettangolo(double x1, double y1, double x2, double y2){
/* Costruisce un rettangolo date le coordinate dei suoi punti diagonalmente opposti */
Pbl = new Punto(x1,y1);
Ptr = new Punto(x2,y2);
}
Giusto? |
|
|
|
|
|
#6 |
|
Senior Member
Iscritto dal: Sep 2005
Città: Torino
Messaggi: 606
|
Giusto!
__________________
"Se proprio dovete piratare un prodotto, preferiamo che sia il nostro piuttosto che quello di qualcun altro." [Jeff Raikes] "Pirating software? Choose Microsoft!" |
|
|
|
|
|
#7 |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
|
|
|
|
|
|
#8 |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
mmm altro dubio...sulle mie dispense la proff fà tutta una cosa lunga per fare un metodo che restituisce il riferimento al vertice inferiore sinistro di un rettangolo...secondo voi questa mia semplice versione è valida:
Codice:
public Punto getBottomLeftCorner(){
Punto P = new Punto(Pbl.getAscissa(), Ptr.getOrdinata());
return P;
}
Visto che il primo costruttore dati due punti qualsiasi si occupa di costruire un rettangolo definito dal vertice inferiore sinistro (Pbl) e dal vertice superiore destro (Ptr) andandosi a calcolare i corretti Pbl e Ptr. A questo punto nel mio metodo posso fare una copia hard di Pbl e restituire il riferimento al nuovo punto, ci può stare? Grazie Andrea |
|
|
|
|
|
#9 | |
|
Senior Member
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
|
Quote:
Visto che la variabile d'istanza (o meglio l'oggetto a cui punta) non è modificabile, puoi passare direttamente quel riferimento. ovvero: Codice:
return this.Pbl
__________________
|
|
|
|
|
|
|
#10 | |
|
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Quote:
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
|
|
|
|
|
#11 |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Punto è un oggetto modificabile perchè come detto nei post precedenti l'esercizio è fatto per avere un metodo traslaLungoX ed un altro metodo traslaLungoY che traslano un punto lungo l'asse X o l'asse Y modificandone le coordinate
|
|
|
|
|
|
#12 |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
|
|
|
|
|
|
#13 | |
|
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Quote:
![]() Da che coordinate stai creando il nuovo oggetto Punto? Ricontrolla, e guarda che vertice individuano.
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
|
|
|
|
|
#14 |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
|
|
|
|
|
|
#15 | |
|
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Quote:
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
|
|
|
|
|
#16 | |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Quote:
Codice:
public Rettangolo(double x1, double y1, double x2, double y2){
/* Costruisce un rettangolo date le coordinate dei suoi punti diagonalmente opposti */
punto1 = new Punto(x1,y1);
punto2 = new Punto(x2,y2);
}
Codice:
/** Restituisce il riferimento ad un oggetto di tipo Punto corrispondente al vertice dell'angolo inferiore sinistro */
public Punto getBottomLeftCorner(){
double nuovaAscissa, nuovaOrdinata; // Per creare un nuovo punto
Punto P; // Il nuovo punto da restituire
if(punto1.getAscissa()<=punto2.getAscissa() && punto1.getOrdinata()<=punto2.getOrdinata())
P = new Punto(punto1.getAscissa, punto1.getOrdinata);
else if(punto1.getAscissa()>punto2.getAscissa() && punto1.getOrdinata()>punto2.getOrdinata())
P = new Punto(punto1.getAscissa, punto2.getOrdinata);
else{
if(punto1.getAscissa()<=punto2.getAscissa())
nuovaAscissa = punto1.getAscissa();
else nuovaAscissa = punto2.getAscissa();
if(punto1.getOrdinata()<=punto2.getOrdinata())
nuovaOrdinata = punto1.getOrdinata();
else nuovaOrdinata = punto2.getOrdinata();
P = new Punto(nuovaAscissa,nuovaOrdinata);
}
return P; // Ritorna il riferimento al punto creato
}
|
|
|
|
|
|
|
#17 |
|
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Non basta scegliere il minimo tra i due sia nel caso dell'ascissa che dell'ordinata?
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
|
|
|
|
#18 | |
|
Senior Member
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
|
Quote:
Non avevo capito che ti servisse proprio avere quei 2 metodi. ![]() EDIT: stavo pensando, il metodo clone() è considerato sicuro per fare copie hard oppure no? Cioè un programmatore che vuole fare copia hard nel suo costruttore può usare tranquillamente il clone (sempre che sia implementato, cosa abbastanza rara) oppure preferisce usare un new con i vari get*() ??? Ci si fida oppure no dei clone() scritti da altri? Penso sia un questione abbastanza teologica... che dicono i padri di Java?
__________________
Ultima modifica di malocchio : 29-11-2008 alle 18:26. |
|
|
|
|
|
|
#19 | |
|
Bannato
Iscritto dal: Mar 2004
Città: Roma
Messaggi: 2682
|
Quote:
|
|
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Feb 2007
Città: Verona
Messaggi: 1060
|
Mi auto-rispondo:
sulle questioni religiose non so, ma ho trovato un pagina interessante riguardo il metodo clone() e i vari problemi che possono nascere con questo: http://java.sun.com/developer/JDCTec...6.html#cloning
__________________
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 06:40.






















