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 は、本来よりも大きな値を返す可能性があると指摘しています。彼は、ユーザー定義の仮想メソッドのより正確なカウントを提供するJCLGetVirtualMethodCountの関数について言及しています。その関数と を使用して、これも 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;

抽象クラスに抽象メソッドがない場合、どの程度抽象化できるのでしょうか? 開発者がインスタンスを作成できないように抽象化されている必要がありますが、どうしてもそうしたい場合はインスタンスを作成できます。そのため、抽象クラスをマークすることは、使用上の実際の制限よりも実際には警告です。

于 2009-05-12T14:25:50.477 に答える
0

TypInfo ユニットをざっと見ても、何の役にも立ちません。「抽象クラス」の概念は、純粋にコンパイラーの利益のためだと思います。このクラスはインスタンス化せず、その子孫のみを適用するというルールを適用しますが、実行時に実際には何もしないため、RTTI を記録する必要はありません。

好奇心だけで、なぜこれを調べようとしているのですか?

于 2009-05-12T14:15:48.950 に答える