Solved

How do I COPY an object?

Posted on 2004-09-22
12
9,407 Views
Last Modified: 2010-10-05
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
Comment
Question by:ajgonzalezm
12 Comments
 
LVL 27

Expert Comment

by:kretzschmar
ID: 12125968
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
 
LVL 13

Expert Comment

by:BlackTigerX
ID: 12126266
the Assign method is the answer as kretzchmar said

this will do

Object2.Assign(Object1);
0
 
LVL 2

Expert Comment

by:__alex
ID: 12130505
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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
LVL 3

Accepted Solution

by:
jpedef earned 50 total points
ID: 12131766
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
 
LVL 6

Expert Comment

by:pritaeas
ID: 12132327
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
 
LVL 3

Expert Comment

by:jpedef
ID: 12132610
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
 
LVL 27

Expert Comment

by:kretzschmar
ID: 12132764
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
 
LVL 3

Expert Comment

by:jpedef
ID: 12140229
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
 
LVL 27

Expert Comment

by:kretzschmar
ID: 12140302
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

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

786 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question