[fpc-pascal] why (ClassType as TMyClass).Create fails

Michalis Kamburelis michalis.kambi at gmail.com
Tue Jun 21 16:27:22 CEST 2016


 2016-06-21 15:57 GMT+02:00 Dennis <dec12 at avidsoft.com.hk>:
> Following up to the cloning example code:
>
> Type
>  TMyClassRef = class of TMyClass;
>
> implementation
>
> function TMyClass.Clone(AOwner: TComponent): TMyClass;
> begin
>   Result := TMyClassRef(ClassType).Create(AOwner);
>
> //but the next line will fail to compile
> //  Result := (ClassType as TMyClassRef).Create(aOwner);
>   Result.Assign(Self);
> end
>
> Isn't (ClassType as TMyClassRef).Create(aOwner)  supposed to be safer
> because sometimes we copy and paste code around and in the end  (ClassType
> might not be a descendant of TMyClass and the compiler won't catch this type
> mismatch if we do
>
>   Result := TMyClassRef(ClassType).Create(AOwner);
>
> Am I missing something?
>

The "is" / "as" operators are just not defined on class references
(they only on classes and interfaces). Not really sure why.

To make the typecast *somewhat* safer (but see disclaimers below) you
can check the InheritsFrom (
http://www.freepascal.org/docs-html/rtl/system/tobject.inheritsfrom.html
) before casting. InheritsFrom is a class method, it can be used on
instances of class references easily.

So like

if ClassType.InheritsFrom(TMyClass) then
  Result := TMyClassRef(ClassType).Create(AOwner) else
  raise Exception.Create(...);

Note that you check for "InheritsFrom(TMyClass)" , not
"InheritsFrom(TMyClassRef)". So it will *not* secure from bugs when
someone changes the definition of TMyClassRef (to be "class of
TSomeOtherClass").

But it will secure from bugs if this code is copy-pasted into some
unrelated class, where ClassType is not compatible with TMyClass.

Actually, since this is inside an instance, you can write
"InheritsFrom(TMyClass)" instead of
"ClassType.InheritsFrom(TMyClass)". Actually you can write "Self is
TMyClass". Which is actually trivially true in this code (this is
inside a TMyClass method)... But maybe some variation of this check
will be useful, if this is used in a more complicated code, with
something less obvious than "ClassType" as an argument.

Regards,
Michalis


More information about the fpc-pascal mailing list