Delphiのインターフェースを使うと、参照カウントが0になったオブジェクトは自動で破棄されます。
この機能を使って、変数がスコープを離れた時にリソースを返却するRAIIを実現できます。
次のサンプルプログラムは、ボタンを押した時に時間のかかる処理を行います。
処理中はカーソルを砂時計にして、処理が終わったらカーソルを元に戻します。
procedure TForm1.Button1Click(Sender: TObject);
var
Save_Cursor: TCursor;
begin
Save_Cursor := Screen.Cursor; //現在のカール祖を保存
Screen.Cursor := crHourGlass; //カーソルを砂時計に変更
try
Sleep(5000); //時間のかかる処理
finally
Screen.Cursor := Save_Cursor; //カーソルを元に戻す
end;
end;
RAIIを使うと、次のようなコードを書くことができます。
コードがずいぶんと見やすくなります。
procedure TForm1.Button2Click(Sender: TObject);
var
Cursor: IRAIICursor;
begin
Cursor := CreateRAIICursor(crHourGlass); //カーソルを砂時計に変更
Sleep(5000); //時間のかかる処理
end; //スコープを離れるとカーソルを元に戻す
実装方法は次のようになります。
type
/// <summary>カーソルを管理するRAIIのインターフェース</summary>
IRAIICursor = interface
end;
/// <summary>RAIIのオブジェクトを取得する</summary>
/// <param name="Cursor">変更するカーソル</param>
/// <returns>RAIIのオブジェクト。実体はTRAIICursorクラス</returns>
function CreateRAIICursor(Cursor: TCursor):IRAIICursor;
implementation
type
/// <summary>IRAIICursorの実装。このクラスは公開しない。</summary>
TRAIICursor = class(TInterfacedObject, IRAIICursor)
private
FCursor: TCursor; //変更前のカーソル
public
constructor Create(Cursor: TCursor);
destructor Destroy; override;
end;
constructor TRAIICursor.Create(Cursor: TCursor);
begin
FCursor := Screen.Cursor;
Screen.Cursor := Cursor;
end;
destructor TRAIICursor.Destroy;
begin
Screen.Cursor := FCursor; //カーソルを元に戻す
end;
function CreateRAIICursor(Cursor: TCursor):IRAIICursor;
begin
Result := TRAIICursor.Create(Cursor);
end;
なかなか便利ではないかと思いますが、いかがでしょうか。
こんにちは。
以下のような利用例でもOKでしょうか?
procedure TForm1.Button1Click(Sender: TObject);
begin
CreateRAIICursor(crHourGlass);
Sleep(2000);
end;
高橋智宏様
ありがとうございます。
変数に代入しなくてもいいのですね。
ちょっと不思議な気もします。
勉強になりました。