クラス参照

提供: Appmethod Topics
移動先: 案内検索

クラスとオブジェクト:インデックス への移動

時には、オペレーションが、クラスのインスタンス(つまりオブジェクト)ではなくクラスそのもので実行されることがあります。これは、たとえば、クラス参照を使ってコンストラクタ メソッドを呼び出すときなどに起こります。特定のクラスをその名前で参照することは必ずできますが、時には、クラスを値とする変数やパラメータを宣言しなければならないことがあり、そのような状況では、クラス参照型が必要になります。

このトピックで扱う内容は次のとおりです。

  • クラス参照型
  • クラス演算子

クラス参照型

クラス参照型(メタクラスと呼ばれることがあります)は、次の構文で示されます。

class of type

ここで、type は任意のクラス型です。識別子 type 自体は、class of type を型とする値を示します。type1type2 の上位型である場合、class of type2type1 のクラスと代入互換性があります。次のコードがあるとします。

  type TClass = class of TObject;
  var AnyObj: TClass;

上記では、任意のクラスの参照を格納できる AnyObj という変数を宣言しています (クラス参照型の定義は変数宣言やパラメータ リストで直接行うことはできません)。任意のクラス参照型の変数に値 nil を代入することができます。

クラス参照型がどう使用されるかを確かめるために、(Classes ユニットにある)Classes.TCollection のコンストラクタの宣言を以下で見てみましょう。

  type TCollectionItemClass = class of TCollectionItem;
       ...
  constructor Create(ItemClass: TCollectionItemClass);

この宣言では、Classes.TCollection インスタンス オブジェクトを作成するには、Classes.TCollectionItem から派生するクラスの名前をコンストラクタに渡す必要があることを記述しています。

クラス参照型は、コンパイル時に実際の型が不明なクラスまたはオブジェクトに対してクラス メソッドや仮想コンストラクタを呼び出す必要がある場合に役に立ちます。

コンストラクタとクラス参照

コンストラクタは、クラス参照型の変数を使って呼び出すことができます。これにより、コンパイル時に型が不明なオブジェクトを作成できます。以下に例を示します。

  type TControlClass = class of TControl;
  
  function CreateControl(ControlClass: TControlClass;
      const ControlName: string; X, Y, W, H: Integer): TControl;
    begin
      Result := ControlClass.Create(MainForm);
      with Result do
        begin
          Parent := MainForm;
          Name := ControlName;
          SetBounds(X, Y, W, H);
          Visible := True;
        end;
    end;

CreateControl 関数には、作成するコントロールの種類を指定するためのクラス参照パラメータが必要です。このパラメータを使用して、そのクラスのコンストラクタを呼び出します。クラス型の識別子はクラス参照値を示すので、CreateControl の呼び出しでは、作成するインスタンスのクラスの識別子を指定できます。以下に例を示します。

  CreateControl(TEdit, 'Edit1', 10, 10, 100, 20);

クラス参照を使って呼び出されるコンストラクタは通常、仮想コンストラクタです。その呼び出しで起動されるコンストラクタ実装は、クラス参照の実行時型によって決まります。

クラス演算子

クラス メソッドはクラス参照に作用します。どのクラスも、ClassType と ClassParent という 2 つのクラス メソッドを TObject から継承します。これらのメソッドはそれぞれ、オブジェクトのクラスの参照と、オブジェクトの直接の上位クラスの参照を返します。どちらのメソッドも TClass 型(TClass = class of TObject)の値を返します。これは、より具体的な型にキャストすることができます。どのクラスも、呼び出し元のオブジェクトが指定のクラスから派生したものかどうかを調べる InheritsFrom というメソッドも継承します。これらのメソッドは is 演算子と as 演算子で使用され、直接呼び出す必要はめったにありません。

is 演算子

is 演算子は、動的な型チェックを実行するもので、オブジェクトの実際の実行時クラスを確認するために使用されます。式は次のとおりです。

object is class

objectclass で示されるクラスまたはその下位クラスのインスタンスである場合は True を返し、そうでない場合は False を返します (オブジェクトが nil の場合、結果は False です)。オブジェクトの宣言された型がクラスに関係ない場合(つまり、型が異なり、一方がもう一方の上位型でない場合)は、コンパイル エラーが発生します。以下に例を示します。

  if ActiveControl is TEdit then TEdit(ActiveControl).SelectAll;

この文では、ActiveControl 変数を TEdit 型にキャストしています。その前にまず、ActiveControl で参照されるオブジェクトが TEdit またはその下位クラスのインスタンスかどうかを確かめます。

as 演算子

as 演算子はチェック済みの型キャストを実行します。式は次のとおりです。

object as class

object と同じオブジェクトの参照を、class で指定された型として返します。実行時にオブジェクトは、class で指定されたクラスまたはその下位クラスのインスタンスか、nil でなければなりません。そうでない場合は、例外が発生します。オブジェクトの宣言された型がクラスに関係ない場合(つまり、型が異なり、一方がもう一方の上位型でない場合)は、コンパイル エラーが発生します。以下に例を示します。

  with Sender as TButton do
   begin
    Caption := '&Ok';
    OnClick := OkClick;
   end;

演算子の優先順位規則により、多くの場合、as による型キャストをかっこで囲む必要があります。以下に例を示します。

  (Sender as TButton).Caption := '&Ok';

関連項目

コード例