[java] cloneable probleem

Pagina: 1
Acties:
  • 125 views sinds 30-01-2008

  • T.T.
  • Registratie: April 2000
  • Laatst online: 22-01 14:13

T.T.

Sowieso

Topicstarter
Ben een klaverjasspel aan het schrijven. Hierbij wil ik dat de computer de kaarten die hij op kan gooien, evalueert. Bijvoorbeeld als hij wil bijgooien, dan kopieert hij het huidige spel en gooit een kaart erbij en kijkt hoeveel punten het zijn.
Vervolgens een nieuwe kopie enz.

stukje code:

private Kaart laagste()
{
int minimum=1000;
Kaart out = null;

for (int i=0; i<aantalGoedeKaarten; i++)
{
Tafel test = deTafel.copy();
test.ApplyMove(goedeKaarten[i]);

if (test.puntenInSlag()<minimum)
{
minimum = test.puntenInSlag();
out=goedeKaarten[i];
}
}
System.out.println("LAAGSTE: "+out.toString());
return out;
}

Tafel is een cloneable klasse. Daarin heb ik een methode copy() gemaakt:

public Tafel copy()
{
Tafel out=null;
try
{out= (Tafel) this.clone();}
catch (Exception e)
{System.out.println("FOUT: "+e);}
return out;
}

Probleem:

in die for-loop van de laagste-methode gebruikt hij steeds dezelfde Tafel, en niet steeds de originele. Ik hou bijvoorbeeld ergens een counter bij, en bij de 2e keer dat ie door de loop gaat gebruikt ie de opgehoogde counter, en niet weer de orginele...Hoe komt dat?

Verwijderd

Weet niet, java is niet mijn sterkste punt :P , maar vraag config eens :) hij zit zich toch te vervelen...

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Misschien kan het komen omdat een Cloneable een shallow copy is. Dit betekent dat dus niet alle referenties ook gekloond worden.
Dit zou het dus kunnen zijn als die counter ergens in een referentie zit.

Ik gebruik Cloneable zelf nooit en gebruik altijd een methode getDeepCopy() (of hetShallowCopy()) waarin ik zelf een object kloon. Dit geeft je veel meer duidelijkheid over wat je aan het doen bent.

Succes,

Martin

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • T.T.
  • Registratie: April 2000
  • Laatst online: 22-01 14:13

T.T.

Sowieso

Topicstarter
Ok thanks. Zal ik zeker een naar kijken. Zou het kunnen zijn omdat mijn cloneable klasse Tafel weer een andere klasse gebruikt en dat ik die niet cloneable heb gemaakt?

mbravenboer:
is dat niet ontzettend veel werk? Dan maakt u dus zelf een nieuwe klasse in die methoden en handmatig geeft u alle attributen dezelfde waarde? Ik heb daar te veel attributen voor :(

  • T.T.
  • Registratie: April 2000
  • Laatst online: 22-01 14:13

T.T.

Sowieso

Topicstarter
Heb even goed naar debugger gekeken. Het is inderdaad zo dat de klasse Tafel en zijn kloon apart staan. Tafel gebruikt weer andere klassen. Bij het clonen worden deze niet gecloned?
In mn debugger is te zien dat het orgineel en de kloon attributen hebben die naar de ZELFDE objecten verwijzen. AGHH. help. hoe los ik dit op?

  • T.T.
  • Registratie: April 2000
  • Laatst online: 22-01 14:13

T.T.

Sowieso

Topicstarter
HELP.. iemand?

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Sorry, modem :'( dus ik check niet vaak.

Ja dit is dus precies het probleem waar ik op doelde. Als je alleen de interface Cloneable implementeert wordt alleen het object zelf gekloond en niet de referenties.

In de java API documentatie van de klasse Object staat daarover:
"The method clone for class Object performs a specific cloning operation. First, if the class of this object does not implement the interface Cloneable, then a CloneNotSupportedException is thrown. Note that all arrays are considered to implement the interface Cloneable. Otherwise, this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation."

Als je dit wel wilt kan je het beter zelf implementeren door of:
* de clone methode de herdefinieren en wel het goede werk te doen.
* helemaal geen gebruik maken van cloneable maar het lekker zelf maken.

Ik heb een interface met de volgende methoden:
<klassenaam> getDeepCopy()
<klassenaam> getShallowCopy()

Nu weet je precies wat er gebeurt. Het is misschien iets meer werk, maar het kan een hoop problemen voorkomen.

Ik neem aan dat je zelf wel kan bedenken hoe je deze methoden moet implementeren?
Je Tafel moet dan de interface implementeren net als alle klassen van de referentie die in tafel zitten.

Succes,

Martin

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22:39
Het is dan de bedoeling dat objecten die als handle in de klasse voorkomen, evenals de klasse zelf, ook de Cloneble interface moeten implementeren, en de clone() methode moeten implementeren. (Ik zie dat niet in jouw code, vergeten ?)

In het object moet je eerst de clone methode van je parent aanroepen (super.clone()), en daarna de clone methode van al je datamembers (niet de primitieven).

Uiteindelijk roept super.clone() Object.clone() aan (Overbodig: Want alle klassen zijn hiervan afgeleid ;))

Deze methode zorgt voor een bitwise copy van je object. De handles, die anders ook zouden worden gekopieerd, worden echter in jouw clone() methode gevuld met goede refs.

Voorbeeld:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Test implements Cloneable {
  public Object clone() {
    Object o = null;
    try {
       o = super.clone();
    } catch (CloneNotSupportedException e) {
       //Ja euhhh...
    }
    return o;
  }
}

public class Composed implements Cloneable {
   private int i=0;
   
   private Test T1=new Test();
   private Test T2=new Test();

   public Object clone() {
     Composed o = null;
     try {
        o = (Composed) super.clone();
     } catch (CloneNotSupportedException e) {
        //Ja euhhh...
     }
     o.T1=(Test)o.T1.clone();
     o.T2=(Test)o.T2.clone();
     return o;
   }
}

Uit: Thinking in Java, Bruce Eckel.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 06-11-2025
Farlane: juist opgemerkt. Alleen ben ik zelf niet zo gecharmeerd van het hele Cloneable systeem. Het is geen fraaie OO en het zorgt voor grote onduidelijkheid en grote kans op vergissingen als je iets vergeet. Zelf zou ik het dus liever gewoon implementeren. Uiteraard moet ik toegeven dat dit meer werk is en je code minder makkelijk aanpasbaar maakt...

Martin

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 22:39
Inderdaad, het is nogal een 'wazige' manier van werken. Maar als je het goed doet, hoef je in ieder geval al je primitieve datamembers (dat kunnen er veel zijn) te kopieren in een custom functie.

Meneer Eckel zegt ook dat het een beetje een hack is, want de Clonable interface zelf is leeg! De clone methode komt voor in de klasse Object, maar is protected.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • T.T.
  • Registratie: April 2000
  • Laatst online: 22-01 14:13

T.T.

Sowieso

Topicstarter
Veel dank :)
Ik ga eerst even alles goed lezen, en dan toepassen. Ben blij te zien dat er mensen met echte kennis van java zijn 8-)

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Dat clonen is toch zo klaar als een klontje..

Als je een klasse cloont dan wordt er een copy van die klasse gemaakt en worden dus ook de waarden die erin staan exact gekopieerd.

DUS OOK de waarden van je referenties. En aangezien de waarde van een referentie een geheugen adres is wijzen dus de referenties van je nieuwe klasse naar dezelfde instantie van een object in je geheugen.

Erg basic spul allemaal ... Als je weet wat een referentie inhoud dan zie je dit al voordat je gaat testen.

Dus je moet het klonen van de objecten in je klasse handmatig doen. (zoals al is aangegeven)

Valt me op dat veel mensen programmeren maar niet precies weten wat er in het geheugen gebeurt. En dat is jammer, want als je snapt hoe iets in het geheugen gebeurt dan snap je een heleboel problemen die je tegenkomt bij het programmeren. :)

Op z'n tijd een klein beetje prutsen met assembler is erg leerzaam :)

  • T.T.
  • Registratie: April 2000
  • Laatst online: 22-01 14:13

T.T.

Sowieso

Topicstarter
DDD - ik wist inderdaad NIET wat er in de java implementatie gebeurde.. met bovenstaande uitleg had ik jouw verhaal ook al verzonnen, maar dat is achteraf makkelijker dan vooraf.
Wat mij betreft had de implementatie van Cloneable ook wel zo kunnen zijn dat ie niet referenties kloonde maar Objecten :)

Beetje vage opmerking dus.

Maar ja, het programma werkt nu, heb bij andere klassen ook clone() toegevoegd. en perfect. Nu nog wat errors eruit halen :'(

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Errors?? Ik eh, omzeil ze liever :p

Maar ja, als andere mensen met je progje moeten werken dan kun je helaas niet anders dan alle fouten proberen af te handelen.

  • boneyard
  • Registratie: Januari 2002
  • Laatst online: 26-11-2022
ik weet niet of iemand dit ook nog leest maar ik het even proberen

meneer T.T. zou je contact met mij willen opnemen op bart_sikkes@hotmail.com het gaat over je poging tot het schrijven van een klaverjas programmma

  • Orphix
  • Registratie: Februari 2000
  • Niet online
aah ... pas bij de onderste post zag ik de datum van de topicstarter :D
ik snapte al niet waarom een lite-mod z'n naam eronder zou zetten *foei* ;)

boneyard, je zou ook kunnen proberen een e-mail te sturen naar 'tt at vulcanus.its.tudelft.nl'

  • D2k
  • Registratie: Januari 2001
  • Laatst online: 31-08 10:19

D2k

Op zaterdag 26 januari 2002 18:06 schreef boneyard het volgende:
ik weet niet of iemand dit ook nog leest maar ik het even proberen

meneer T.T. zou je contact met mij willen opnemen op bart_sikkes@hotmail.com het gaat over je poging tot het schrijven van een klaverjas programmma
right
niet zo dus

Doet iets met Cloud (MS/IBM)

Pagina: 1

Dit topic is gesloten.