• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 11044
  • Last Modified:

How do I COPY an object?

Let's say I have this in Delphi 7:

TMyObject=Class(TObject)
    Field1: String;
end;

var
    Object1,Object2: TMyObject;
begin
    Object1:=TMyObject.Create;
    Object1.Field1:='ONE';
    Object2:=TMyObject.Create;
    Object2:=Object1; (*)
end;

As I understand, the sentence marked with * makes Object2 POINT TO Object1 and I left an space in memory, that was allocated by "Object2:=TMyObject.Create;", that can not be referenced.

A. Is this correct?

B. What I really need is to have a COPY in memory of Object1 called Object2 so that they are totally independent from each other. How can I accomplish this?

Thanks a lot in advance.


Regards AJ.
0
ajgonzalezm
Asked:
ajgonzalezm
1 Solution
 
kretzschmarCommented:
try this change

TMyObject=Class(TPersistent)  //persitent class introduces the assign method
    Field1: String;
end;

var
    Object1,Object2: TMyObject;
begin
    Object1:=TMyObject.Create;
    Object1.Field1:='ONE';
    Object2:=TMyObject.Create;
    Object2.Assign(Object1); //use assign for copy properties, maybe u must add a property
end;

not tested, just from head

meikl ;-)
0
 
BlackTigerXCommented:
the Assign method is the answer as kretzchmar said

this will do

Object2.Assign(Object1);
0
 
__alexCommented:
consider an object with fields that are objects;

TYourClass = class
private
  anotherObject: TAnotherClass;
end;

If you don't want to derive from TPersistent (I guess the Assign method needs some additional information: published properties..., not sure about that) you can write your own Assign method.

TYourClass = class
public
  procedure Assign(const source: TYourClass);
private
  s: string;
  anotherObject: TAnotherClass;
end;

procedure TYourClass.Assign(const source: TYourClass);
begin
  // Copy all data
  s := source.s;
  anotherObject.Assign(source.anotherObject);   // You have to imlement TAnotherClass.Assign
end;

Usage:

var
    Object1,Object2: TYourClass ;
begin
    Object1:=TYourClass.Create;
    Object2:=TYourClass.Create;
    Object2.Assign(Object1);
end;
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
jpedefCommented:
Assign doesn't work unless you write somekind of copying procedure.
Compile TMyObject with TypeInfo {$M+} or derive it from TPersistent.

Then you can use typeinfo to copy published properties from one object to another.

procedure CopyObject(Source, Dest: TMyObject);
var
  TypInfo: PTypeInfo;                                                        
  PropList: TPropList;
  PropCount, i: integer;
  Value: variant;
begin
  TypInfo := Source.ClassInfo;
  PropCount := GetPropList(TypInfo, tkAny, @PropList);
  for i := 0 to PropCount - 1 do
  begin
    Value := GetPropValue (Source, PropList [i]^.Name);
    SetPropValue (Dest, PropList [i]^.Name, Value);
  end;
end;
0
 
pritaeasSoftware EngineerCommented:
That works for published properties, but that doesn't work if you have an array property. Or any other custom class as property for that matter. Assign() is the way to go.
0
 
jpedefCommented:
Its not the name of the procedure.
Assign doesn't solve anything and you must anyway override Assign (or AssignTo) procedure if you want to use it with your custom object.

That typeinfo example could also be in overridden Assign or AssignTo procedure (I've used that many times).
And yes, you can only copy published properties with typeinfo, but if you want to copy anything else (private, public ...) you need to write your own copy procedure (Assign or not).

I must admit that this typeinfo example is slow, becase it uses variants insterad of "real" types. If efficiency comes to way you should also check typekind of property and use different methods for different types instead. You should also check if property setter is present (readonly properties) and that you really can copy that specific kind of property (arrays, classes).
0
 
kretzschmarCommented:
from my point of view its enough to derive it from TPersistent
(just not sure if a published property is needed),
but in case of need the type looks like

TMyObject=Class(TPersistent)  
    Field1: String;
published
  property F1 : String read Field1 write Field1;
end;

after this assign should work properly

meikl ;-)

0
 
jpedefCommented:
You should take a look of TPersistent's Assign implementation.
Or just try it. Assign raises error "Cannot assign a TMyObject to a TMyObject'.
0
 
kretzschmarCommented:
well,
i have currently no delphi on hand,
but i will do a test later,
guess the assign method is virtual at tpersistent

in this case you are correct, jpedef,
and it should better derived from TComponent,
or with your suggestion

meikl ;-)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now