2016-06-21 15:57 GMT+02:00 Dennis :
Show quoted text 25 lines
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