Toon posts:

[java] clone method

Pagina: 1
Acties:
  • 104 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
hoi
ik heb even in mijn boeken van java info over clone method opgezocht, in het boek thinking in java
heb ik precies willen verstaan
dat wanneer men een object clonet de methode van de base class moet opzoeken die alle primitieve variabelen kopieert.
En dat men voor de reference variabelen altijd zelf een clone method moet oproepen
Klopt dit?

Ook las ik dat niet alle standaard klassen clone ondersteunen dus is het niet altijd practisch dit te gebruiken.
In thinking in java wordt aangeraden geen copyconstructors te gebruiken, hoe staan jullie hiertegenover, tot nu toe heb ik altijd met copyconstructors gewerkt.
Is dit wel goed practice zo ja waarom, zo neen waarom

alvast dank

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09-05 08:08

Janoz

Moderator Devschuur®

!litemod

In mijn eigen projecten ben ik nog niet aangelopen tegen een moment waar ik de clone nodig had, maar ikzelf zou toch voor de clone gaan waneer ik in die situatie zou komen. Mijn grootste reden hiervoor is consistentie. Wanneer je copy constructors gebruikt zul je intern, zodra je bij een class aankomt die niet door jezelf geimplementeerd is, alsnog de clone methode aan moeten roepen.

Wanneer jij je software openbaar maakt en anderen gaan je libraries gebruiken, dan zullen ze goed moeten administrereen bij welke class welke manier nodig is om een kopie van het object te maken. Dit maakt het alleen maar nodeloos ingewikkeld.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Sinds Java 5.0 ga ik voor clone omdat je dan niet meer hoeft te casten. Daarvoor zou ik om castings redenen voor copy constructor gaan.

Verwijderd

Topicstarter
de voornaamste reden waarom ik copyconstructors ook gebruikte is omdat de clone methode tamelijk ingewikkeld te vatten is neem nu je moet je super.clone aanroepen om de primitieve variabelen in jou klasse te gebruiken, logischerwijze zou je eerst denken dat die enkel de variabelen kopieert van je super klasse, en niet die van je eigenlijke klasse., de clone method op je reference variabelen is dan wel logisch als je een deep copy wilt.

Persoonlijk sta ik hier to sceptisch tegenover, nu ja het zit in de api dus moeten we dit maar proberen enigzins mogelijk te vatten

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09-05 08:08

Janoz

Moderator Devschuur®

!litemod

In principe implementeer je in de copy constructor exact dezelfde code als bij de clone method. Het enige verschil is hoe je de source krijgt. Je kunt zelfs heel simpel een clone methode implementeren mbv de copyConstructor.

code:
1
2
3
public Object clone(){
  return new MyClass(this);
}

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 10-05 05:42
Ik sluit met bij Janoz aan: de clone method als de copy constructor doen hetzelfde, maar de clone method is onderdeel van de Java 'standaard' en zorgt er samen met de Cloneable interface voor dat je klassen ook door derden bruikbaar zijn. Die verdient dus de voorkeur, ook al kleeft er het (grote) nadeel aan dat 'ie niet type-safe is (al is dat in Java 1.5 verholpen en dan is het natuurlijk een uitgemaakte zaak).

Daarbij is het lastig een copy constructor te implementeren als je superklasse die niet ook implementeert (want dan moet je terugvallen op het gebruik van clone in de constructor, wat een beetje slechte mix van stijlen oplevert).

Verwijderd

Topicstarter
ja dat zou natuurlijk tof zijn, dan kan ik een copyconstructor als private constructor zetten en die teruggeven in de clone method
Janoz schreef op woensdag 02 maart 2005 @ 13:22:
In principe implementeer je in de copy constructor exact dezelfde code als bij de clone method. Het enige verschil is hoe je de source krijgt. Je kunt zelfs heel simpel een clone methode implementeren mbv de copyConstructor.

code:
1
2
3
public Object clone(){
  return new MyClass(this);
}

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 14:11

RayNbow

Kirika <3

Een geval van mogelijk verkeerd gebruik van copy constructors in Java: http://www.codeguru.com/java/tij/tij0128.shtml#Heading381

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 10-05 05:42
Ligt het aan mij dat ik het punt van schrijvers van Java-artikelen nooit begrijp, of komt dat omdat die schrijvers de concepten die ze beschrijven niet kennen? Kan iemand me uitleggen wat er nu mis gaat volgens de auteur?

Zoals ik het zie gebruikt hij een copy constructor en laat zien dat je daarmee een kopie kan maken die een superklasse is van het oorspronkelijke object. En om een of andere reden is dit verkeerd ('oops!') en werkt dat in C++ anders. Maar volgens mij is dit noch verkeerd noch verschilt het van de werking van copy constructors in C++.

Wat wel belangrijk is is het verschil tussen clone() en een copy constructor: clone() levert een kopie van het object op zelf op, terwijl je met een copy constructor een klasse instantieert die mogelijk niet overeenkomt met de meest specifieke klasse van het object.

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09-05 08:08

Janoz

Moderator Devschuur®

!litemod

Verwijderd schreef op woensdag 02 maart 2005 @ 13:33:
ja dat zou natuurlijk tof zijn, dan kan ik een copyconstructor als private constructor zetten en die teruggeven in de clone method
Het punt wat ik hiermee wilde maken was juist dat het maken van een clone methode niet makkelijker of moeilijker is dan het implementeren van een copy constructor. Zet je immers de constructor inline in de methode dan heb je je clone methode ook al. Dat je in de war raakt over de clone methode kan eigenlijk maar 2 dingen betekenen:
1 Je denkt veel te moeilijk.
2 Je doet het ook al fout bij de copy constructor.

Feit blijft dat het enige verschil tussen beide methodes persoonlijke voorkeur is, en in dit geval is mijn persoonlijke voorkeur consistentie en dus de door sun geadviseerde standaard te gebruiken.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Topicstarter
ja zou best wel kunnen hoor dat ik 1 van die 2 fouten maak, maar het is toch onlogisch dat je via een super.clone oproep je klasse waar je voor het ogenblik inzit kunt dupliceren - ik zou akkoord zijn moesten we zeggen dat gewoon de super klasse wordt gekloond maar in mijn boeken lees ik dat hierdoor de variabelen van mijn huidige klasse ook gekloond worden.

Misschien is het een gebrek aan ervaring in programmatie mijnentwege hoor

Verwijderd

In principe maakt het geen kloot uit wat je gebruikt (uitgaande van 1.5) zijn het beide exact dezelfde methodes. Wat wel een verschil is is de betekenis. clone impliceert expliciet een exactie kopie van het orgineel waar een copy constructor dat niet doet. In het geval van bijvoorbeeld een Arraylist zou je bij het kopieren de grootte van de array aan kunnen passen aan de gebruikte grootte van het orgineel (en dus niet de capaciteit)

edit:
en ik vergeet nog een belangrijk punt, misschien wel het belangrijkste. het schiet me opeens te binnen.
Stel de class Object heeft een copy contructor en ik maak een instantie van de class Integer aan. Ik doe vervolgens:
Java:
1
2
Object o1 = new Integer(1);
Object o2 = new Object(o1);

In het geval van clone wordt de mehode uit Integer wel aangeroepen en nu dus niet. We hebben dus braaf een copy van een Object maar alles over de Integer zijn we kwijt.

[ Voor 39% gewijzigd door Verwijderd op 02-03-2005 15:18 ]


  • ronaldmathies
  • Registratie: Juni 2001
  • Niet online
Offtopic:

Je kan de clone ook gebruiken met behulpt van het serialisen van objecten.
Dan krijg je ook een gecloonde versie maar je hoeft er nooit code voor te schrijven.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  public final Object clone() {
    try {
      ByteArrayOutputStream bout = new ByteArrayOutputStream();
      ObjectOutputStream out = new ObjectOutputStream(bout);
      out.writeObject(this);
      out.close();

      ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
      ObjectInputStream in = new ObjectInputStream(bin);
      Object cloned = in.readObject();
      in.close();

      return cloned;
    } catch (Exception e) {
      return null;
    }
  }


Dit werkt alleen bij classe die Serializable zijn maar het is een hele makkelijke manier.

[ Voor 12% gewijzigd door ronaldmathies op 02-03-2005 17:01 ]

3015 Wp-z 5360 Wp-nno op 2 x SMA-SB3600 TL-21, Warmtepomp: ERSC-VM2CR2 / PUHZ-SHW140 YHA, WTW Q350, EV Kia Ev6 GT-Line


Verwijderd

Wat een voordeel is van serializatie gebruiken voor clonen is dat ook je inner classes en final fields meegaan. Een nadeel is dat het een stuk langzamer is.

Zie ook: http://www.javaworld.com/.../02-qa-0124-clone-p1.html
http://www.artima.com/intv/bloch13.html
en http://xstream.codehaus.org/ (hoewel ik niet bepaald een fan ben van Codehaus, lijkt dit wel een aardig project)

  • ronaldmathies
  • Registratie: Juni 2001
  • Niet online
Dat het trager is kan kloppen, alleen gebruik je de clone method meestal niet x keer achter elkaar. Dus ik ondervindt de traagheid niet.

3015 Wp-z 5360 Wp-nno op 2 x SMA-SB3600 TL-21, Warmtepomp: ERSC-VM2CR2 / PUHZ-SHW140 YHA, WTW Q350, EV Kia Ev6 GT-Line


  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 10:16
Verwijderd schreef op woensdag 02 maart 2005 @ 14:44:
ja zou best wel kunnen hoor dat ik 1 van die 2 fouten maak, maar het is toch onlogisch dat je via een super.clone oproep je klasse waar je voor het ogenblik inzit kunt dupliceren - ik zou akkoord zijn moesten we zeggen dat gewoon de super klasse wordt gekloond maar in mijn boeken lees ik dat hierdoor de variabelen van mijn huidige klasse ook gekloond worden.

Misschien is het een gebrek aan ervaring in programmatie mijnentwege hoor
Zover ik weet kopieert de super.clone juist alleen maar de variabelen die in je superclass zitten. De variabelen die je in je huidige class toegevoegd hebt (als uitbreiding op je superclass) moet je hierna zelf nog kopiëren.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

riezebosch schreef op donderdag 03 maart 2005 @ 14:23:
[...]


Zover ik weet kopieert de super.clone juist alleen maar de variabelen die in je superclass zitten. De variabelen die je in je huidige class toegevoegd hebt (als uitbreiding op je superclass) moet je hierna zelf nog kopiëren.
Als je zorgt dat je hoogste super klasse een call maakt naar zijn super.clone() welke de clone() van Object is, dan zorgt die ervoor dat je een instantie terug krijgt van dezelfde classe als waarvan het object is. Knap he?

"Beauty is the ultimate defence against complexity." David Gelernter


Verwijderd

Topicstarter
sorry maar dit snap ik echt niet meer hoor, kun je het een beetje specifieker uitleggen want zoals ik het begrijp gebeurt er in de super.clone iets magisch die ervoor zorgt dat je object waar je de super.clone oproept niet enkel de super variabelen cloont maar werkelijk alles alsook de variabelen van je object waar je de super in oproept is dit juist?
Macros schreef op donderdag 03 maart 2005 @ 14:34:
[...]


Als je zorgt dat je hoogste super klasse een call maakt naar zijn super.clone() welke de clone() van Object is, dan zorgt die ervoor dat je een instantie terug krijgt van dezelfde classe als waarvan het object is. Knap he?

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 10:16
Macros schreef op donderdag 03 maart 2005 @ 14:34:
[...]


Als je zorgt dat je hoogste super klasse een call maakt naar zijn super.clone() welke de clone() van Object is, dan zorgt die ervoor dat je een instantie terug krijgt van dezelfde classe als waarvan het object is. Knap he?
Haha, dat klinkt meer als een ranzige hack. Blijkbaar doet Object dit dan native ofzo? Op zich is dit overbodig, wanneer ieder niveau zorgdraagt voor het aanroepen van Clone van het bovenliggende niveau en het kopieren van het huidige niveau.

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack


Verwijderd

---
nevermind, aannames maken op de onzin die hierboven staat is niet handig.

[ Voor 193% gewijzigd door Verwijderd op 03-03-2005 15:36 ]


  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

Object.clone gebruikt memcpy(), een C functie. Daarbij kopieert hij het hele object in 1 keer. Dus alle primitives en referenties van het huidige object, waar de oorspronkelijke .clone() op wordt geroept, worden gekopieerd. Dus die hoef je dan niet meer zelf te kopieren. Dit heeft als voordeel dat het heel snel is en dat je nooit perongelijk een referentie of primitive kan vergeten.

"Beauty is the ultimate defence against complexity." David Gelernter


Verwijderd

Macros schreef op donderdag 03 maart 2005 @ 15:38:
Object.clone gebruikt memcpy(), een C functie. Daarbij kopieert hij het hele object in 1 keer. Dus alle primitives en referenties van het huidige object, waar de oorspronkelijke .clone() op wordt geroept, worden gekopieerd. Dus die hoef je dan niet meer zelf te kopieren. Dit heeft als voordeel dat het heel snel is en dat je nooit perongelijk een referentie of primitive kan vergeten.
Leuk voor collecties :o

  • Macros
  • Registratie: Februari 2000
  • Laatst online: 30-04 09:28

Macros

I'm watching...

Doet geen deep cloning, dus het kloont niet de objecten die worden gereferenced.

"Beauty is the ultimate defence against complexity." David Gelernter


Verwijderd

Topicstarter
maar als je die dan weer expleciet laat clonen heb je dus wel een deep clone????
Macros schreef op donderdag 03 maart 2005 @ 15:53:
[...]

Doet geen deep cloning, dus het kloont niet de objecten die worden gereferenced.

Verwijderd

Topicstarter
Verwijderd schreef op donderdag 03 maart 2005 @ 15:55:
maar als je die dan weer expleciet laat clonen heb je dus wel een deep clone????

wat eigenlijk logisch is dan


[...]

  • riezebosch
  • Registratie: Oktober 2001
  • Laatst online: 10:16
Verwijderd schreef op donderdag 03 maart 2005 @ 15:31:
---
nevermind, aannames maken op de onzin die hierboven staat is niet handig.
:?

Canon EOS 400D + 18-55mm F3.5-5.6 + 50mm F1.8 II + 24-105 F4L + 430EX Speedlite + Crumpler Pretty Boy Back Pack

Pagina: 1