クラス参照
クラスとオブジェクト:インデックス への移動
時には、オペレーションが、クラスのインスタンス(つまりオブジェクト)ではなくクラスそのもので実行されることがあります。 これは、たとえば、クラス参照を使ってコンストラクタ メソッドを呼び出すときなどに起こります。 特定のクラスをその名前で参照することは必ずできますが、時には、クラスを値とする変数やパラメータを宣言しなければならないことがあり、そのような状況では、クラス参照型が必要になります。
このトピックで扱う内容は次のとおりです。
- クラス参照型
- クラス演算子
クラス参照型
クラス参照型(メタクラスと呼ばれることがあります)は、次の構文で示されます。
class of type
ここで、type は任意のクラス型です。識別子 type 自体は、class of type を型とする値を示します。type1 が type2 の上位型である場合、class of type2 は type1 のクラスと代入互換性があります。次のコードがあるとします。
type TClass = class of TObject;
var AnyObj: TClass;
上記では、任意のクラスの参照を格納できる AnyObj という変数を宣言しています (クラス参照型の定義は変数宣言やパラメータ リストで直接行うことはできません)。任意のクラス参照型の変数に値 nil を代入することができます。
クラス参照型がどう使用されるかを確かめるために、System.Classes.TCollection (System.Classes ユニット内)のコンストラクタの宣言を見てみましょう:
type TCollectionItemClass = class of TCollectionItem;
...
TCollection = class(TPersistent)
...
constructor Create(ItemClass: TCollectionItemClass);
この宣言では、TCollection インスタンス オブジェクトを作成するには 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
は、object が、class で示唆されたクラスかその下位クラスのいずれかのインスタンスである場合には True を返し、そうでなければ False を返します。(object が nil の場合、結果は False となります。)object の宣言型が class に関係ない場合 -- つまり、型が明らかに異なり、一方が他方の上位型でなかった場合、コンパイル エラーとなります。例:
if ActiveControl is TEdit then TEdit(ActiveControl).SelectAll;
この文では、ActiveControl
変数を TEdit 型にキャストしています。その前にまず、ActiveControl
で参照されるオブジェクトが TEdit
またはその下位クラスのインスタンスかどうかを確かめます。
as 演算子
as 演算子はチェック済みの型キャストを実行します。式は次のとおりです。
object as class
は、同じオブジェクトへの参照を object として返しますが、class で指定された型で返します。実行時、object は、class で示唆されたクラスかその下位クラスのいずれかのインスタンスであるか、nil でなければなりません。そうでなければ、例外が発生します。object の宣言型が class に関係ない場合 -- つまり、型が明らかに異なり、一方が他方の上位型でなかった場合、コンパイル エラーとなります。 例:
with Sender as TButton do
begin
Caption := '&Ok';
OnClick := OkClick;
end;
演算子の優先順位規則により、多くの場合、as による型キャストをかっこで囲む必要があります。以下に例を示します。
(Sender as TButton).Caption := '&Ok';
関連項目
- クラスとオブジェクト(Delphi)
- フィールド(Delphi)
- メソッド(Delphi)
- プロパティ(Delphi)
- ネストした型宣言
- 例外(Delphi)
- 演算子のオーバーロード(Delphi)
- クラス ヘルパとレコード ヘルパ(Delphi)