6

在 Delphi 中是否可以使用 RTTI(或其他东西)来检查一个类是否被声明为抽象?就像是:

TMyAbstractClass = class abstract(TObject)
  // ...
end;

...

if IsAbstract(TMyAbstractClass.ClassInfo) then
  ShowMessage('Yeah')
else
  ShowMessage('Computer says no...');
4

2 回答 2

6

我没有足够新的版本来直接回答您的问题,但请记住,该类是否是抽象的并不重要。所做的只是让编译器阻止你直接在类上调用构造函数。如果您将类引用放入类引用变量中,编译器将允许您调用该变量的构造函数,并且在运行时您将拥有一个本应不可实例化的类的实例。

var
  c: TClass;
  o: TObject;
begin
  c := TMyAbstractClass;
  o := c.Create;
  Assert(o is TMyAbstractClass);
end;

真正重要的是该类是否有任何抽象方法。你可以很容易地检查。查看班级的 VMT。任何包含指向指针的虚方法槽System._AbstractError都是抽象方法。棘手的部分是知道要检查多少虚拟方法槽,因为没有记录。Allen Bauer 在对另一个问题的回答中演示了如何做到这一点,但在评论中 Mason Wheeler 指出它可能会返回比应有的更大的值。他提到了JCL中的函数,它应该更准确地计算用户定义的虚拟方法。使用该函数 和,同样来自 JCL,我们得到了这个函数:GetVirtualMethodCountGetVirtualMethod

function HasAbstractMethods(c: TClass): Boolean;
var
  i: Integer;
begin
  Result := True;
  for i := 0 to Pred(GetVirtualMethodCount(c)) do
    if GetVirtualMethod(c, i) = @_AbstractError then
      exit;
  Result := False;
end;

如果一个抽象类没有抽象方法,那么它到底能有多抽象呢?它必须被标记为抽象以防止开发人员创建它的实例,但如果你真的想要,无论如何你都可以创建它的实例,所以标记一个抽象类实际上更像是一个警告,而不是对使用的任何实际限制。

于 2009-05-12T14:25:50.477 回答
0

快速浏览 TypInfo 单元并没有发现任何帮助。我认为“抽象类”的概念纯粹是为了编译器的利益。它给了它一个强制执行的规则——没有这个类的实例化,只有它的后代——但在运行时并没有真正做任何事情,所以没有必要为它记录任何 RTTI。

只是出于好奇,你为什么要找出这个问题?

于 2009-05-12T14:15:48.950 回答