检查clasparent是否是类型X(不是:等于类型X)



我在一个类函数中,想知道父类类型是否为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个更正:

  1. ClassParent.InheritsFrom(TVMDNode)代替ClassParent is TVMDNode
  2. 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.

最新更新