Recent

Author Topic: Clone Objects?  (Read 11829 times)

dst

  • New Member
  • *
  • Posts: 10
Clone Objects?
« on: October 04, 2009, 01:07:10 pm »
Is there a way to clone objects (copy a instance without any references)?

b:=a; creates a reference:
Code: [Select]
var
  a,b:TMyClass;
begin
  a:=TMyClass.create;
  a.myVariable:=myValue1;
  b:=a; // This creates a reference
  b.myVariable:=myValue2; //also changes a.myVariable
end;

Vincent Snijders

  • Administrator
  • Hero Member
  • *
  • Posts: 2661
    • My Lazarus wiki user page
Re: Clone Objects?
« Reply #1 on: October 04, 2009, 01:15:47 pm »
Not out of the box. If TMyClass descends from TPersistent and overrides Assign, you can do:
Code: [Select]
var
  a,b:TMyClass;
begin
  a:=TMyClass.create;
  a.myVariable:=myValue1;
  b:=TMyClass.Create;
  b.Assign(a);
  b.myVariable:=myValue2; //does not change a.myVariable
end;

cdbc

  • Hero Member
  • *****
  • Posts: 2727
    • http://www.cdbc.dk
Re: Clone Objects?
« Reply #2 on: October 05, 2009, 03:43:04 am »
Hi Dst.
In most cases I would go with Vincents solution, nice and clean.
Some times however, one has to do something like this:
Code: [Select]
TMyClass = class
private
  fInt: integer;
  fStr: string;
  ...
protected
  ...
public
  function Clone: TMyClass;
  property IntProp: integer read fInt write fInt;
  property StrProp: string read fStr write fStr;
  ...
end;

implementation

...
{ !!! user is responsible for freeing the object, resulting from this function !!! }
TMyClass.Clone: TMyClass;
begin
  Result:= TMyClass.Create;
  with Result do begin
    IntProp:= fInt;
    StrProp:= fStr;
    ...
  end;
end;


With a complex class, this approach could be a lot of work. Then again, it's basically the same you're doing, when you're overriding TPersistent.Assign().
On the memory-freeing issue, one could choose to use interfaces and let refcounting sort it out  ;)

Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6/QT6 -> FPC Release -> Lazarus Release &  FPC Main -> Lazarus Main

dst

  • New Member
  • *
  • Posts: 10
Re: Clone Objects?
« Reply #3 on: October 05, 2009, 07:44:30 pm »
Is it better to use TPersistent, or create a own clone method?
Or is there a possibility without cloning every depending variable by its own (~100 %))?
Or a possibility to auto-create that poece of code?

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12301
  • Debugger - SynEdit - and more
    • wiki
Re: Clone Objects?
« Reply #4 on: October 05, 2009, 09:25:25 pm »
You can create your own assign or clone in your own object, if you don't want TPersistent.

You should be aware, that while you can just copy integers or strings (dest.FString1 = src.FString1) => you may not want to do so with any objects that are stored in your object. You would have to create a new instance, and assign it separately.

There is no way to fully autocreate the assign procedure. But if you know regular expression replaces, you can speed up the process considerably.
Copy the declaration of all variables, so you have
 FVal1: Integer;
 FStr1, FStr2 : String;

- Replace all "," (comma) by newline
- replace all ":.*?;" by nothing
Then you should have each identifier on a line of it's own
- replace:  (\S*)
  with: dest.$1 := src.$1;

You so need to keep it in sync, if you add new variables.


dst

  • New Member
  • *
  • Posts: 10
Re: Clone Objects?
« Reply #5 on: October 08, 2009, 09:36:39 pm »
Thanks :)

Much better solution that typing and typing and typing and typing... ;)

 

TinyPortal © 2005-2018