Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (581)
games submitted by our members
Games in WIP (500)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  how to clone objects(method is protected)  (Read 2065 times)
0 Members and 1 Guest are viewing this topic.
Offline h3ckboy
« Posted 2010-01-04 15:04:58 »

so as the title states, I am wondering how to clone objects, because the method clone() is protected so I cannot really use it.

thx in advance,
h3ckboy
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2010-01-04 15:19:13 »

1. implement the java.lang.Cloneable interface
2. override the clone() method.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline h3ckboy
« Reply #2 - Posted 2010-01-04 15:24:49 »

wouldnt I then have to know how to clone method works?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline JL235

JGO Coder


Medals: 10



« Reply #3 - Posted 2010-01-04 15:42:35 »

wouldnt I then have to know how to clone method works?
If you read the API you'll see:
Quote from: JavaAPI
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.
So extend the class, add on the Clonable interface and override the clone method with a public version that calls up to the original.

You can also do this with reflection:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
    public static <T> T clone(T object)
            throws IllegalArgumentException, IllegalAccessException, InstantiationException
    {
        final Class<T> klass = (Class<T>) object.getClass();
        final T copy = klass.newInstance();

        copyFields( object, copy );

        return copy;
    }

    public static <T> void copyFields(T source, T dest)
            throws IllegalArgumentException, IllegalAccessException
    {
        final Class<?> klass = source.getClass();
       
        for ( Field field : klass.getDeclaredFields() ) {
            field.set( dest, field.get(source) );
        }
    }

Should work, but that code is untested. It also presumes the class of the object being copied has a no argument constructor.

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #4 - Posted 2010-01-04 15:51:43 »

The problem with  someClass.newInstance(); is that there must be a public (no-arg) constructor, and boy... if it has side-effects...

private and final fields are also a problem, not always fixable with setAccessible(true) because the JIT will optimize final fields and changing the actual field, might not always update the value used in calculations inside method bodies (ask: OrangyTang / search the JGO forum for the thread)

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline JL235

JGO Coder


Medals: 10



« Reply #5 - Posted 2010-01-04 15:57:38 »

private and final fields are also a problem, not always fixable with setAccessible(true) because the JIT will optimize final fields and changing the actual field, might not always update the value used in calculations inside method bodies (ask: OrangyTang / search the JGO forum for the thread)
I agree, it's vastly better to do this without reflection then with. But depending on what he wants it should be good enough.

Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 12


Game Engineer


« Reply #6 - Posted 2010-01-04 16:35:28 »

You don't even need to override clone(), you can just roll your own if you need more options.

Ex.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
//Default initializer.
public MyClass()
{
    id = getNextID();
    x = 4;
    y = 1000;
}

public MyClass(MyClass cloner)
{
    x = cloner.getX();
    y = cloner.getY();
    id = cloner.getID();
}

public MyClass(MyClass cloner, int newID)
{
    x = cloner.getX();
    y = cloner.getY();
    id = newID;
}

See my work:
OTC Software
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 605
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #7 - Posted 2010-01-04 16:39:11 »

eww! Smiley

Don't use public constructors to expose such functionality.
Create private constructors and public methods, or better, the FactoryPattern/BuilderPattern

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline h3ckboy
« Reply #8 - Posted 2010-01-04 16:43:53 »

ahh so, basically you recreate the object?

so you just give the new object all of the variables that the current one has?

this kinda defeats the purpose of my goal then, I can do it a better way....

thank you for helping me understand,
h3ckboy
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 12


Game Engineer


« Reply #9 - Posted 2010-01-04 19:03:35 »

eww! Smiley

Don't use public constructors to expose such functionality.
Create private constructors and public methods, or better, the FactoryPattern/BuilderPattern
What's the problem doing it this way? Instead of
1  
MyObject clone = (MyObject) clonedObject.clone();

you just have
1  
MyObject clone = new MyObject(clonedObject);


It doesn't seem like you're inherently exposing anything other than the ability to create a copy of another object, which is what you want to accomplish with clone anyway. But yes, you could do it like this too:
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  
public MyClass()
{
    id = getNextID();
    x = 4;
    y = 1000;
}

private MyClass(MyClass cloner)
{
    x = cloner.getX();
    y = cloner.getY();
    id = cloner.getID();
}

public Object clone()
{
    return new MyClass(this);
}

//or if you don't want to use clone()

public MyClass getClone()
{
    return new MyClass(this);
}


I don't necessarily understand why that's better - it leaves you with the same functionality in the end. The only difference is you're not directly allocating a new object, you're leaving that to the class's method.

Doesn't using the builder pattern concept seem a bit bloated if he just wants a clone? I guess if you're moving towards what I defined above (different ways of cloning something with different parts and pieces) then the builder pattern could work well, but it seems extraneous just to clone.

And yeah, h3ckboy, you do it all manually, in the end. If you really wanted to you could externally create a new object and then use public mutators and accessors to assign all the data you needed - it's all just a question of implementation.

See my work:
OTC Software
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline jezek2
« Reply #10 - Posted 2010-01-04 19:13:54 »

The clone method is there for a reason: it can clone any subclass and gives you exactly the same type, whereas with constructor you're creating some concrete type and not really a clone. The constructor approach is considered a bad practice.

Also clone method does shallow copy for you automatically, though you have to still do deep copy manually, but that's leaved to programmer because it can't be decided automatically which field should or shouldn't be deep copied.

One probably overlooked feature in Java 5 and newer is that you can override clone method and change the method signature to return your type. Though you have to override it for every subclass to return the concrete type in every case.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 12


Game Engineer


« Reply #11 - Posted 2010-01-04 21:22:45 »

The clone method is there for a reason: it can clone any subclass and gives you exactly the same type, whereas with constructor you're creating some concrete type and not really a clone. The constructor approach is considered a bad practice.

Also clone method does shallow copy for you automatically, though you have to still do deep copy manually, but that's leaved to programmer because it can't be decided automatically which field should or shouldn't be deep copied.

One probably overlooked feature in Java 5 and newer is that you can override clone method and change the method signature to return your type. Though you have to override it for every subclass to return the concrete type in every case.
Aha, that makes sense. Thanks for enlightening me on that. As I wrote that code above, I did indeed wonder if clone() has yet been adjusted to allow different return types (I suspected it probably had). Good to know you can do that now.

See my work:
OTC Software
Offline pjt33
« Reply #12 - Posted 2010-01-04 23:18:09 »

Aha, that makes sense. Thanks for enlightening me on that. As I wrote that code above, I did indeed wonder if clone() has yet been adjusted to allow different return types (I suspected it probably had). Good to know you can do that now.
It didn't need adjusting. Covariant return types are a general language feature, and any (non-final) virtual method supports them.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 12


Game Engineer


« Reply #13 - Posted 2010-01-05 00:52:26 »

It didn't need adjusting. Covariant return types are a general language feature, and any (non-final) virtual method supports them.
Didn't Jezek say that being able to do that with clone() added with Java 5? That's what I meant when I said "adjusted."

See my work:
OTC Software
Offline pjt33
« Reply #14 - Posted 2010-01-05 10:44:39 »

Didn't Jezek say that being able to do that with clone() added with Java 5? That's what I meant when I said "adjusted."
He did, but that's a narrow reading of what he said. It would be more precise to say that the ability to do that with any (non-final) virtual method was added in Java 5. clone() wasn't singled out for special treatment.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 12


Game Engineer


« Reply #15 - Posted 2010-01-05 15:54:01 »

He did, but that's a narrow reading of what he said. It would be more precise to say that the ability to do that with any (non-final) virtual method was added in Java 5. clone() wasn't singled out for special treatment.
Which is a logical thing to have added with templates - to be honest I didn't know they had added that feature, though. It's certainly a good one to know about.

See my work:
OTC Software
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (55 views)
2014-04-15 18:08:23

BurntPizza (53 views)
2014-04-15 03:46:01

UprightPath (66 views)
2014-04-14 17:39:50

UprightPath (49 views)
2014-04-14 17:35:47

Porlus (66 views)
2014-04-14 15:48:38

tom_mai78101 (90 views)
2014-04-10 04:04:31

BurntPizza (151 views)
2014-04-08 23:06:04

tom_mai78101 (247 views)
2014-04-05 13:34:39

trollwarrior1 (204 views)
2014-04-04 12:06:45

CJLetsGame (211 views)
2014-04-01 02:16:10
List of Learning Resources
by SHC
2014-04-18 03:17:39

List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!