2009-05-12 16 views
6

DelphiではRTTI(または他のもの)を使用して、クラスが抽象として宣言されているかどうかを調べることは可能ですか? のような何か:Delphiクラスが抽象宣言されているかどうかをチェックする方法は?

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

... 

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

この質問に与えられた答えは、ヘルプが役立つかもしれないこの質問に与えられた答えは、http://stackoverflow.com/questions/791004/how-can-i-detect-if-a-delphi-class-has-a-virtual-constructor。 – RobS

答えて

0

TypInfoユニットを介して簡単に見は役に立ち何かを上げていません。私は "抽象クラス"の概念は純粋にコンパイラの利益のためだと思う。このクラスのインスタンス化はなく、その子孫のみですが、実際には実行時に何もしないので、RTTIを記録する必要はありません。

なぜあなたは好奇心のためにとにかくこれを見つけようとしていますか?

+0

私は共通の祖先を持つ異なるクラス型(TCollectionItem)を含むことができるTCollection派生クラスを持っています。具体的には、異なるタイプの列を含むグリッド列コレクションです。そして今、私はユーザーが(TClassFinderを使用して)登録された列型を追加できるようにするdesigntimeコレクションエディタを作成したいと思います。しかし、私はこのエディタでabtractクラスを望んでいません。私の抽象クラスはTCustom *という名前になっていますので、今はクラス名を使ってフィルタリングしています。 – mrMoo

+0

したがって、あなたの問題は抽象クラスを検出する方法ではありません。あなたの問題は、有効な "列の種類"のリストを取得する方法です。簡単な解決策は、有効な列タイプであるクラスのみを登録することです。最初に抽象クラスを登録しないでください。クラスを登録する唯一の理由は、クラスを名前で検索してインスタンス化できることです。インスタンス化されることはないクラスを登録しないでください。 VCLは独自の「カスタム」ベースクラスも登録していません。 –

+0

はい、非常に真実ですが、問題は、あなたが示唆するように「有効」なクラスだけを登録することですが、Delphiは自動的に親クラスも登録します。 RegisterClass(TButton)を使用してTButtonを登録すると、DelphiはTCustomButton、TButtonControlなども登録します。とにかく、非常に興味深い抽象メソッドについてのあなたの記事のためにとにかく私の質問への正しい答えは "いいえ"だと思います – mrMoo

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のコメントでは、より大きな値が返される可能性があることを指摘しています。彼はJCLからGetVirtualMethodCount関数を記述しています。これにより、より正確なユーザー定義の仮想メソッドが得られるはずです。その後、抽象クラスは何の抽象メソッドを持っていない場合は

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; 

、どのように抽象それは本当にすることができ:JCLからも、その機能とGetVirtualMethodを使用して、我々は、この機能を取得しますか?開発者がそのインスタンスを作成できないようにするには、アブストラクトとマークされていなければなりませんが、実際に使用したい場合は、インスタンスを作成することができます。

+0

残念ながら、私はいくつかのテストを実行したとき、Allenのアルゴリズムはすべての場合に動作しないことが判明。私はそれを少し調べて、それが分かるようにすればその質問に訂正を投稿します。 –

+0

名前の前に他のものが置かれているようです。 Allenのアルゴリズムではなく、JCLSysUtils.GetVirtualMethodCountを試してみてください。これは、GetVirtualMethodと同じJCLユニットに置かれるのが便利です。 –

+0

確かに。 JCLバージョンでは、VMT内の他のすべてのポインタがチェックされ、最初の仮想メソッドとクラス名の間にポインタがあれば、仮想メソッドの範囲と見なされるウィンドウが「短縮」されます。 –

関連する問題