Frage

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.

War es hilfreich?

Lösung

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.

Andere Tipps

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:

  1. Replacing ClassParent is TVMDNode with ClassParent.InheritsFrom(TVMDNode)
  2. Change the typecast 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.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top