PDA

View Full Version : copying values between objects.



noeska
20-05-2007, 08:10 PM
How do i make an copy/clone of an object.
E.g. i want to copy vars from one existing object to another existing object.
This works as long as i do not free the object i copied from.
How do i make a real copy with values instead of references? So that i can free the object i copied from and continue using the object i copied to.

Thanks for your help in advance.

Setharian
20-05-2007, 08:33 PM
if you mean creating a "deep" copy, then there is no generic way which would work on all objects....you have to create a constructor which takes object of the same type as one of its arguments and there you have to copy all the values manually....after that you can use the constructor to create clones....

M109uk
20-05-2007, 08:35 PM
The only way i can think of is if you added an assign procedure into the object..



procedure TObject.Assign(const Source: TObject);
begin
var1 := Source.var1;
var2 := Source.var2;
.. etc ..
end;


In the case where you have TObject2 = Class(TObject) you can make the Assign a virtual procedure and you can do..



procedure TObject2.Assign(const Source: TObject); override;
begin
inherited Assign(Source);
If (Source Is TObject2) Then
Begin
newVar1 := TObject2(Source).newVar1;
newVar2 := TObject2(Source).newVar2;
End;
end;


Hope this helps :)

wodzu
21-05-2007, 07:38 AM
I don't know which compiler you are using but in Delphi you have Assign method already defined. However it works only for the descendants of the TPersistent class.

savage
21-05-2007, 08:41 AM
Assuming you use properties to hold you important information, IIRC you should be able to use RTTI to copy the values over. In either case the correct way to do it is by implementing an *Assign* method.

noeska
21-05-2007, 06:05 PM
Should i use Assign or AssignTo for this, i started writing AssignTo as i believe Assign is dependen on Assignto i believe, but i am not sure.

@savage: how do i use: IIRC you should be able to use RTTI to copy the values over.


Hmm the real problem was array of TMesh.
It should also have an Assign method. Also for the copy i should make new TMeshes and assign the values to these.

WILL
21-05-2007, 08:06 PM
Hey noeska,

Since I use objects with about every gaming project I make this is an issue that I deal with all the time. My solution is to make my own function that clones all the values.

procedure TGameObject.Clone(Original: TGameObject);
begin
X := Original.X;
Y := Original.Y;
// etc... for all values
end;

Much like M109uk's Assign procedure above. This allows you to make a clean looking loop for things like removing one of an array of weapon shots that hit their target for example.

savage
21-05-2007, 10:38 PM
@savage: how do i use: IIRC you should be able to use RTTI to copy the values over.

I don't have a specific example to hand, but I found the legendary Brian long has a solution in this zip file...
http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.zip



The RTTIUnit.pas unit that accompanies this paper has a routine called CopyObject defined in it. CopyObject takes two object references - a source object and a target object. It iterates through all the published properties in the source object and attempts to set the value of the same property in the target. If the property doesn’t exist in the target then it skips onto the next one.

I think this is quite an elegant solution.

Which is taken from this article here - http://www.blong.com/Conferences/BorConUK98/DelphiRTTI/CB140.htm

Setharian
22-05-2007, 06:24 AM
and it is a lot slower than just declaring the copy function by yourself + it does handle deep copying classes only partially - from RTTI you can get class type info and out of that class reference, but that's all, you do not know how to clone the nested classes (that is using standard .Create constructor you can create it, but not assign any data do it)....

User137
08-06-2007, 12:04 PM
I made this little code that uses Streams. Not very elegant solution and it does not work with tree like objects. You can manually iterate every sub-object though, this style is for saving fixed length blocks of data to stream or file. On the positive side, copying objects can't get any faster than this :P

For managing size of data block you need to give out first var, last var and size of the last one.
http://mureakuha.com/koodikirjasto/1013

Why not use records instead? Because these objects can have functions with them as well.

wodzu
25-06-2007, 01:35 PM
and it is a lot slower than just declaring the copy function by yourself + it does handle deep copying classes only partially - from RTTI you can get class type info and out of that class reference, but that's all, you do not know how to clone the nested classes (that is using standard .Create constructor you can create it, but not assign any data do it)....

Thats not true. Few days ago I wrote simple recursive procedure which allows me to copy entire object which can consist as many subobjects as I want. RTTI is great feature, of course you need to have a subobject exported to a property but that is not a big problem, isn't it?

And that elegance...I just love it;)

Setharian
25-06-2007, 05:21 PM
how do you copy the subobject if it has no RTTI? :) like TList/TObjectList and the like....

wodzu
26-06-2007, 07:16 AM
how do you copy the subobject if it has no RTTI? :) like TList/TObjectList and the like....

Ok you can't but at least you can copy its items;-)

cronodragon
11-07-2007, 03:53 PM
Just an idea. You could use a Hash Table to store your properties associated to strings, then the objects could easily exchange them. If performance is important, you could use this hash-table object as a transmitter, making one object to export all it's properties to the transmitter, and then the other object to import the properties from it.