如何检查Delphi类是否被声明为abstract?

mrM*_*Moo 6 delphi rtti

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

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

...

if IsAbstract(TMyAbstractClass.ClassInfo) then
  ShowMessage('Yeah')
else
  ShowMessage('Computer says no...');
Run Code Online (Sandbox Code Playgroud)

Rob*_*edy 6

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

var
  c: TClass;
  o: TObject;
begin
  c := TMyAbstractClass;
  o := c.Create;
  Assert(o is TMyAbstractClass);
end;
Run Code Online (Sandbox Code Playgroud)

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

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;
Run Code Online (Sandbox Code Playgroud)

如果抽象类没有抽象方法,那么抽象方法究竟有多抽象?它必须被标记为抽象以防止开发人员创建它的实例,但如果你真的想要,你可以创建它的实例,所以标记一个抽象类实际上是一个警告,而不是任何实际的使用限制.


Mas*_*ler 0

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

你为什么只是出于好奇而试图找出这一点?