Delphi 2009 無名メソッド・匿名関数 (Anonymouse Method) - Delphi 2009

Delphi 2009でサポートされた無名メソッド(匿名メソッド)を使ってみます。 まず、フォームにボタンを1つ配置して下記のコードを書きます。

実行して、ボタンを押すとビープが鳴ります。シンプルです。 あまり意味がないような気もします・・・。

次に、別のボタンを配置し、下記のコードを記述します。

実行し、ボタンを押すと下図の実行結果が得られます。

なんか、怪しげな挙動をします。GetFunctionで与えた引数が保持された形で、関数ポインタが返されるようです。クラスを定義してメンバ変数に値を入れるような処理が簡単に記述できます。(処理が追いかけにくいので、可読性は落ちるような気もしますが・・・)

さらに、下記のコード記述してみました。
ボタンを配置し、ボタンのイベントといくつかのメソッドを実装

クラス定義部に、TThreadを派生させたスレッドクラスTMyThreadを定義

派生スレッドクラスTMyThreadの実装


このプログラムを実行し、Button3を押すと下図の実行結果が得られます。


手続き的にマルチスレッドプログラムを記述することができます。
便利かもしれません



プログラム全体

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  Tproc= reference to procedure;
  TMyFunc = reference to function(input:string):string;

  TMyThread = class(TThread)
  public
    Name:string;
    Proc:Tproc;
    procedure execute; override;
  end;


  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    function GetFunction(init:string):TMyFunc;
    { Private 宣言 }
  public
    procedure ExecFor(proc:Tproc;Name:string);
    procedure ThreadTerminate(Sender:TObject);
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TMyThread.execute;
begin
  inherited;
  Proc;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  f: Tproc;
begin
  f:=procedure
  begin
    beep;
  end;

  f;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  f:TMyFunc;
begin
  f:=GetFunction('Phase1:');
  Memo1.Lines.Add(f('wait'));
  Memo1.Lines.Add(f('wait..'));
  Memo1.Lines.Add(f('wait....'));
  Memo1.Lines.Add(f('OK! Complete'));

  f:=GetFunction('Phase2');
  Memo1.Lines.Add(f('wait'));
  Memo1.Lines.Add(f('wait..'));
  Memo1.Lines.Add(f('wait....'));
  Memo1.Lines.Add(f('OK! Complete'));


end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  ExecFor(procedure
  begin
    sleep(12000);
  end,'スレッド1'
  );

  ExecFor(procedure
  begin
    sleep(5000);
  end,'スレッド2'
  );

  ExecFor(procedure
  begin
    sleep(7000);
  end,'スレッドだばー'
  );
end;

procedure Tform1.ExecFor(proc:Tproc;Name:string);
var
  mt:TMyThread;
begin
  mt:=TMyThread.Create(true);
  mt.Proc:=proc;
  mt.Name:=Name;
  mt.OnTerminate:=form1.ThreadTerminate;
  mt.Resume;
end;

procedure Tform1.ThreadTerminate(Sender:TObject);
begin
  Memo1.Lines.Add(TMyThread(Sender).Name+ 'Terminated');
end;


function TForm1.GetFunction(init:string):TMyFunc;
begin
  result:=function (input:string):string
  begin
    result:=init+input;
  end;

end;

end.


著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2008-09-20
iPentec all rights reserverd.