Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Duplicating a class with "self.classtype.create" , is this allowed?

68 views
Skip to first unread message

Arthur Hoornweg

unread,
Aug 1, 2008, 4:35:42 AM8/1/08
to
Hello all,

I would like to equip an ancestor class (and all of its descendants)
with the
possibility to create an identical and yet independant "clone" of
themselves.

Would the following approach work?

(I would override the procedure "cloneproperties" in each descendant
to copy any additional properties that the descendant introduces.)

Type tmybaseclass= class
ftest:string;
Function clone: tMybaseclass;
Procedure cloneProperties (from: tmybaseclass); Virtual;
end;

Function tmybaseclass.clone: tMybaseclass;
var t:tclass;
begin
t:=self.classtype; // --> Would this work for descendants?
result:=t.create;
result.cloneProperties(tmybaseclass(self));
end;

Procedure tmybaseclass.cloneProperties (from: tmybaseclass);
begin
//in descendants,call "inherited" before copying new properties.
ftest:=from.ftest;
end;

--
Arthur Hoornweg

(In order to reply per e-mail, please just remove the ".net"
from my e-mail address. Leave the rest of the address intact
including the "antispam" part. I had to take this measure to
counteract unsollicited mail.)

Jürgen Krämer

unread,
Aug 1, 2008, 5:24:27 AM8/1/08
to

Hi,

this only works if neither the base class nor its descendants are
supposed to do some work in their constructors. That's because
ClassType returns a TClass which in turn is a "class of TObject" and
so only knows about TObject.Create.

If you need constructors in the descendants try the following:

Type
TMyBaseClassClass = class of TMyBaseClass;

tmybaseclass= class
ftest:string;
Function clone: tMybaseclass;
Procedure cloneProperties (from: tmybaseclass); Virtual;

constructor Create; virtual;
end;

Function tmybaseclass.clone: tMybaseclass;
var t: TMyBaseClassClass;
begin
t := TMyBaseClassClass(self.classtype);
result:=t.create;
result.cloneProperties(self);
end;

Procedure tmybaseclass.cloneProperties (from: tmybaseclass);
begin
//in descendants,call "inherited" before copying new properties.
ftest:=from.ftest;
end;

constructor TMyBaseClass.Create;
begin
inherited Create;
// only to provide a virtual constructor
end;

Regards,
Jürgen

--
Sometimes I think the surest sign that intelligent life exists elsewhere
in the universe is that none of it has tried to contact us. (Calvin)

Remy Lebeau (TeamB)

unread,
Aug 1, 2008, 6:26:54 AM8/1/08
to

"Arthur Hoornweg" <antispam...@casema.nl.net> wrote in message
news:4892...@newsgroups.borland.com...

> Would the following approach work?

Almost.

> I would override the procedure "cloneproperties" in each
> descendant to copy any additional properties that the
> descendant introduces.

If you derive the ancestor from TPersistent then you can override its
Assign() or AssignTo() method instead of introducing your own method.

> t:=self.classtype; // --> Would this work for descendants?

You need to remove the "Self" portion so you get the correct polymorphic
ClassType, otherwise you will be creating ancstor instances every time.

function TMyBaseClass.Clone: TMyBaseClass;
begin
Result := ClassType.Create; // <-- no 'Self'
Result.CloneProperties(Self);
end;


Gambit


Remy Lebeau (TeamB)

unread,
Aug 1, 2008, 6:28:06 AM8/1/08
to

"Jürgen Krämer" <j...@habel.de> wrote in message
news:4892...@newsgroups.borland.com...

> this only works if neither the base class nor its descendants are


> supposed to do some work in their constructors. That's because
> ClassType returns a TClass which in turn is a "class of TObject"
> and so only knows about TObject.Create.

Good catch, I missed that one.


Gambit


Arthur Hoornweg

unread,
Aug 1, 2008, 7:14:59 AM8/1/08
to
Remy Lebeau (TeamB) wrote:

> You need to remove the "Self" portion so you get the correct polymorphic
> ClassType, otherwise you will be creating ancstor instances every time.

That's a nice gotcha...

Arthur Hoornweg

unread,
Aug 1, 2008, 7:25:39 AM8/1/08
to
Jürgen Krämer wrote:

> Function tmybaseclass.clone: tMybaseclass;
> var t: TMyBaseClassClass;
> begin
> t := TMyBaseClassClass(self.classtype);
> result:=t.create;
> result.cloneProperties(self);
> end;


Thanks, that helped a lot!

Rob Kennedy

unread,
Aug 1, 2008, 9:47:13 AM8/1/08
to

No, ClassType and Self.ClassType are the same things. ClassType is not a
virtual function, but it still acts polymorphically because it fetches
its data from the object's VMT. Ultimately, all ClassType does is return
the four-byte value at the address of the object. That is the TClass
reference for the object, and it is the run-time type of the object.

ClassType and Self.ClassType are the same, just like DefaultHandler and
Self.DefaultHandler are the same, and FieldAddress and Self.FieldAddress
are the same, and Free and Self.Free are the same. THey're al methods of
TObject, and when called from within a method, they are applied to the
object on which the calling method was called, Self.

--
Rob

0 new messages