Reputation: 3879
I am in a class function and want to find out if the parent class type is of the type TVMDNode .
"ClassParent is TVMDNode" does not work. (I do NOT want "ClassParent = TVMDNode").
How do I accomplish this task of doing a chain-check through the class hierarchy without requring the descendant classes to implement its own logic?
type
TOID = string;
TOIDPath = array of TOID;
class function TVMDNode.IsSupported(ANode: TOID): boolean; virtual;
begin
result := true;
end;
class function TVMDNode.Supports(ANodePath: TOIDPath): boolean; // not virtual;
var
n: integer;
begin
// Check if the last segment is supported by our class
n := Length(ANodePath);
if not IsSupported(ANodePath[n-1]) then
begin
result := false; Exit;
end;
SetLength(ANodePath, n-1);
// Recursively check if the previous segments are supported by the parent class, as long as they are of type TVMDNode (and therefore have the Supports() function)
// This logic is implemented in the base class TVMDNode only and shall be applied to every descendant class without requiring override
if ClassParent is TVMDNode then // <-- operator not applicable to this operand type
begin
if not (TVMDNode(ClassParent).Supports(ANodePath)) then
begin
result := false; Exit;
end;
end;
result := true; Exit;
end;
The code should be compatible until Delphi 6.
Upvotes: 0
Views: 333
Reputation: 14832
I think you're misunderstanding Delphi's is operator.
It doesn't do what you think it does.
It does do what you want it to do.
Try the following:
LVar := TList.Create;
if LVar is TList then ShowMessage('Var is a TList');
if LVar is TObject then ShowMessage('Var is also a TObject');
However ClassParent
returns a TClass
and so you can't use is. However, you can use InheritsFrom
. I.e.
if ClassParent.InheritsFrom(TVMDNode) then
Disclaimer: However, you might what to rethink your design. As a general rule you want to avoid all that typecasting. In OO each object has a particular type so that you know what you can do to it. Subclassing means you can do all the same things you could do to the ancestor. However overridden virtual methods may do things differently.
Upvotes: 7
Reputation: 3879
Somebody has given the answer that I should use InheritsFrom
which was the correct answer. The answer was deleted for some reason.
I had to do 2 corrections in the code:
ClassParent is TVMDNode
with ClassParent.InheritsFrom(TVMDNode)
TVMDNode(ClassParent)
to TVMDNodeClass(ClassParent)
.type
TVMDNodeClass = class of TVMDNode;
if ClassParent.InheritsFrom(TVMDNode) then
begin
if not (TVMDNodeClass(ClassParent).Supports(ANodePath)) then
begin
result := false; Exit;
end;
end;
The following code will demonstrate that the chain checking in Support() does work as expected:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TVMDNode = class(TObject)
public
class procedure Supports;
end;
TVMDNodeClass = class of TVMDNode;
TA = class(TVMDNode);
TB = class(TA);
class procedure TVMDNode.Supports;
begin
WriteLn('Do stuff in ' + Self.ClassName);
if ClassParent.InheritsFrom(TVMDNode) then
begin
TVMDNodeClass(ClassParent).Supports;
end;
end;
var
b: TB; s: string;
begin
b := TB.Create;
b.Supports; // will output the correct chain TB -> TA -> TVMDNode
Readln(s);
end.
Upvotes: 1