我在一个类函数中,想要查明父类类型是否属于TVMDNode类型。
" ClassParent是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。
答案 0 :(得分:7)
我认为你误解了德尔福的是运营商。
它没有做你认为它做的事 它确实做你想做的事。
尝试以下方法:
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中,每个对象都有一个特定的类型,以便您知道可以对它做什么。子类化意味着您可以对祖先做同样的事情。但是,重写的虚拟方法可能会采取不同的方式。
答案 1 :(得分:1)
有人给出了我应该使用InheritsFrom
的答案,这是正确的答案。答案因某种原因被删除了。
我必须在代码中进行2次更正:
ClassParent is TVMDNode
ClassParent.InheritsFrom(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.