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?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
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
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

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
batsoftCommented:
{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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.