在Delphi中是否可以使用RTTI(或其他)来检查类是否被声明为抽象? 类似的东西:
TMyAbstractClass = class abstract(TObject)
// ...
end;
...
if IsAbstract(TMyAbstractClass.ClassInfo) then
ShowMessage('Yeah')
else
ShowMessage('Computer says no...');
答案 0 :(得分:6)
我没有最近的版本可以直接回答您的问题,但请记住,类是否为抽象的确实无关紧要。所做的就是让编译器阻止你直接在类上调用构造函数。如果将类引用放入类引用变量中,编译器将允许您在变量上调用构造函数,并且在运行时您将拥有所谓的不可实例化类的实例。
var
c: TClass;
o: TObject;
begin
c := TMyAbstractClass;
o := c.Create;
Assert(o is TMyAbstractClass);
end;
真正重要的是班级是否有任何抽象方法。你可以很容易地检查它。查看班级的VMT。包含指向System._AbstractError
的指针的任何虚方法槽都是一种抽象方法。棘手的部分是知道要检查多少个虚拟方法槽,因为没有记录。 Allen Bauer demonstrated how to do that回答another question,但在评论中,Mason Wheeler指出它可能会返回比它应该更大的值。他提到GetVirtualMethodCount
中的JCL函数,它可以更准确地计算用户定义的虚拟方法。使用该函数和GetVirtualMethod
,也来自JCL,我们得到了这个函数:
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;
如果抽象类没有抽象方法,那么抽象方法究竟有多抽象?它必须被标记为抽象以防止开发人员创建它的实例,但如果你真的想要,你可以创建它的实例,所以标记一个抽象类实际上是一个警告,而不是任何实际的使用限制。
答案 1 :(得分:0)
快速查看TypInfo单元并没有提供任何有用的信息。我认为“抽象类”的概念纯粹是为了编译器的好处。它给了它一个规则来强制执行 - 没有这个类的实例化,只有它的后代 - 但是在运行时没有真正做任何事情,因此不需要为它记录任何RTTI。
为什么你只是出于好奇而试图找出这个?