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

时间:2014-05-12 15:02:08

标签: delphi oop

我在一个类函数中,想要查明父类类型是否属于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。

2 个答案:

答案 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次更正:

  1. ClassParent is TVMDNode
  2. 替换ClassParent.InheritsFrom(TVMDNode)
  3. 将类型转换TVMDNode(ClassParent)更改为TVMDNodeClass(ClassParent)

  4. 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.