Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if a Delphi class is declared abstract?

Tags:

delphi

rtti

Is it possible in Delphi to use RTTI (or something else) to check if a class is declared as abstract? Something like:

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

...

if IsAbstract(TMyAbstractClass.ClassInfo) then
  ShowMessage('Yeah')
else
  ShowMessage('Computer says no...');
like image 832
mrMoo Avatar asked May 12 '09 12:05

mrMoo


1 Answers

I don't have a version recent enough to answer your question directly, but keep in mind that it doesn't really matter whether the class is abstract. All that does is make the compiler stop you from calling a constructor directly on the class. If you put the class reference into a class-reference variable, the compiler will allow you to call the constructor on the variable, and at run time you'll have an instance of the supposedly uninstantiable class.

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

What's really important is whether the class has any abstract methods. You can check for that fairly easily. Look in the class's VMT. Any virtual-method slot that contains a pointer to System._AbstractError is an abstract method. The tricky part is knowing how many virtual-method slots to check, since that isn't recorded. Allen Bauer demonstrated how to do that in an answer to another question, but in the comments Mason Wheeler points out that it may return larger values than it should. He mentions the GetVirtualMethodCount function from the JCL, which should give a more accurate count of user-defined virtual methods. Using that function and GetVirtualMethod, also from the JCL, we get this function:

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;

If an abstract class has no abstract methods, then how abstract can it really be? It must have been marked abstract to prevent developers from creating instances of it, but if you really want to, you can create instances of it anyway, so marking an abstract class is really more of a warning than any actual restriction on usage.

like image 126
Rob Kennedy Avatar answered Sep 20 '22 19:09

Rob Kennedy