Cloning of objects

How do I give an object a method, so that it can clone itself to a new object of the same type. The objects will have the same ancestor but I will not know precise type at design time.

See my last comment for an answer
Of cource it can be done by testing IF (Original is TypeA) then Clone := TypeA.Create else IF (original is TypeB....

but it must can be done in a better way.              
jphAsked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
batsoftConnect With a Mentor Commented:
{First we need declare virtual constructor at
 ffor base class TFoo}
class
 TFoo = class
 private
 FirstField:Integer;
  public
    Constructor CreateFoo;virtual;
....
end;
 THoo =  class(TFoo)
  public
    Constructor CreateFoo;override;
 .......
end;
{in descendants we will override constrcutor and use this}

function Clone(Src:TFoo):TFoo; {can be hoo from foo or any from Foo}
begin
  Result := (Src.Class.ClassType as TFoo).CreateFoo;
  Move(Result.FirstField,Src.FirstField,SizeOF(Src));
end;
0
 
HeapsterCommented:
WHat about writing a .Clone method for all your objects, and creating a copy of the object in there, then changing the parent property to whatever is appropriate.
0
 
jphAuthor Commented:
For 100 points, I would like to see an small example with objects OriginalA and OriginalB inherited fra TOriginalA and a Cloned, that will be of type TOriginalA if Cloned := OriginalA.Clone and of type TOriginalB if Cloned := OriginalB.Clone;
0
Receive 1:1 tech help

Solve your biggest tech problems alongside global tech experts with 1:1 help.

 
gysbert1Commented:
Surely each descendant can have its own clone method. The original has a clone method declared as virtual. That way, whatever type the object is, it will call its own clone method....

Is it really this simple or have I missed something here?
0
 
jphAuthor Commented:
Edited text of question
0
 
jphAuthor Commented:
This was the kind of answer I was looking for:

unit CloneUnit;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, EnhButtn;
type
  TForm1 = class(TForm)
    Label1: TLabel;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

TFoo = class
  Name : string;
  constructor Create; virtual;
  constructor Clone(const aFoo: TFoo);
  function CloneMyself: TFoo; virtual;
  procedure WhoIAm; virtual;
end; {TFoo}


THoo = class(TFoo)
  constructor Create; override;
  constructor Clone(const aHoo:THoo);
  function CloneMyself: TFoo; override; // note return type
  procedure WhoIAm; override;
end; {TGoo}

var
  Form1: TForm1;

implementation

{$R *.DFM}

constructor TFoo.Create;
begin
  Name := 'Testing Foo';
end;

constructor TFoo.Clone(const aFoo: TFoo);
begin
  name  := aFoo.name;
end;

function TFoo.CloneMyself: TFoo;      {virtual}
begin
      Result := Clone(self);
end;      {CloneMyself}

procedure TFoo.WhoIAm;      {override}
begin
   ShowMessage('I am a TFoo ');
end;      {WhoIAm}

 
constructor THoo.Create;
begin
  Name := 'Testing Hoo';
end;

constructor THoo.Clone(const aHoo: THoo);
begin
  name  := aHoo.name;
end;

function THoo.CloneMyself : TFoo;      {virtual}
begin
      Result := Clone(self);
end;      {CloneMyself}


procedure THoo.WhoIAm;      {override}
begin
   ShowMessage('I am a THoo ');
end;      {WhoIAm}


procedure TForm1.Button2Click(Sender: TObject);
var
  a, b: TFoo;
  s: string;
begin
  a := THoo.Create;      // polymorphic creation
  b := a.CloneMyself;      // b doesn't know what it'll be
  b.WhoIAm;
end;

end.

0
 
cucumberCommented:
Clone is too "java"ish. Have a look at TPersistent.Assign.  That's the delphi way to do it.
0
 
sleachCommented:
I found this example in the Delphi Help files.  I think it might be an easy way to do what you want...

Example

type
  {A variable of type TComponentRef can be set at run time to refer to TComponentClass or any of its subclasses}
  TComponentRef = class of TComponentClass;

var
  TCRef: TComponentRef;
  NewComponent: TComponent;
begin
TCRef := TButton; {TCRef can now be used anywhere the name of the class TButton could be used}
NewComponent := TCRef.Create; {TCRef is used here to create a new TButton}
end;

0
All Courses

From novice to tech pro — start learning today.