我在一个类函数中,想知道父类类型是否为TVMDNode类型。
" clasparent is TVMDNode"不起作用。(我不想要"ClassParent = TVMDNode").
我如何在不要求后代类实现自己的逻辑的情况下完成通过类层次结构进行链检查的任务?
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;
代码应该兼容到Delphi 6。
我想你误解了Delphi的是操作符。
它并不像你想象的那样。
你想让它做什么它就做什么。
尝试以下操作:
LVar := TList.Create;
if LVar is TList then ShowMessage('Var is a TList');
if LVar is TObject then ShowMessage('Var is also a TObject');
然而,ClassParent
返回TClass
,所以你不能使用是。但是,您可以使用InheritsFrom
。例如
if ClassParent.InheritsFrom(TVMDNode) then
免责声明:但是,您可能需要重新考虑您的设计。作为一般规则,您希望避免所有类型转换。在OO中,每个对象都有一个特定的类型,这样您就知道可以对它做什么。子类化意味着你可以对祖先做同样的事情。然而,被重写的虚拟方法可能会做不同的事情。
有人给了答案,我应该使用InheritsFrom
,这是正确的答案。由于某些原因,答案被删除了。
我必须在代码中做2个更正:
- 用
ClassParent.InheritsFrom(TVMDNode)
代替ClassParent is TVMDNode
- 将
TVMDNode(ClassParent)
类型转换为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;
下面的代码将演示Support()中的链检查按预期工作:
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.