Reputation: 3517
I have TParentObj = class(TComponent)
and TChildObj = class (TParentObj)
. In addition I have a TCustomObj = class of TParentObj
.
I'm then wanting to create an object of Type parent OR Type Child depending on what a variable is. If 'child' is selected then a TChildObj
should be created and so on.
In the function I have a var: obj : TCustomObj
.
and then I'm trying to do:
if oReturnType = TChildObj
obj := TChildObj.create
else if oReturnType = TParentObj
obj := TParentObj.create
oReturnType
is set and passed in elsewhere.
If I use 'is' instead of '=' I receive the error that the operator is not applicable to this operand type and if I use = instead I get an incompatible types error between TCustomObj
and both TChildObj
and TParentObj
.
I've searched quite a bit but have yet to discover what I'm doing wrong and hoping someone here might be able to shed some light on it.
Thanks in advance.
Upvotes: 1
Views: 2291
Reputation: 84540
First off, it appears that you've missed one of the most important points of TClass
variables: they have access to constructors, and to virtual constructors.
If you put a constructor on TParentObj
and declare it virtual;, and then have all descendants override; that constructor as needed, then a TClass
variable declared as class of TParentObj
will have access to this virtual constructor, and will behave exactly as you'd expect a virtual method to behave:
obj := oReturnType.Create();
//invoke the virtual constructor on the actual type of oReturnType
This technique is used extensively in the VCL; it's at the core of Delphi's form streaming system, for example. TComponent
defines a virtual constructor whose signature is (AOwner: TComponent)
, and every custom component and control that needs a new constructor overrides this one. It's a very useful system, and if you look at the way it works you'll quickly gain an appreciation for the techniques involved.
But as for the actual problem, you're getting an incompatible types error between TCustomObj
and both TChildObj
and TParentObj
because they're not compatible types.
TChildObj
and TParentObj
are object classes, and TCustomObj
is a metaclass, or class variable. A TParentObj
variable represents an object, whereas TCustomObj
, which is defined as class of TParentObj
, represents the class itself, not an object of that class. Declare obj
as TParentObj
(which will accept an object instance of TParentObj
or any of its descendants) and you'll be good.
Upvotes: 4
Reputation: 19096
You can use the classtype TCustomObj
to create the instance
function ObjFactory( AClass : TCustomObj ): TParentObj;
begin
Result := AClass.Create;
end;
procedure foo;
var
LObj : TParentObj;
begin
// instance of TParentObj
LObj := ObjFactory( TParentObj );
// or instance of TChildObj
LObj := ObjFactory( TChildObj );
end;
Upvotes: 2