2012年12月12日水曜日

関数のメソッドポインタ

メソッドポインタでfunctionを使った例のサンプルです。
あまり見当たらなかったので、備忘録がわりに公開しときます。


【メソッドポインタ経由でfunctionを呼び出すサンプル】


unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    LabeledEdit1: TLabeledEdit;
    LabeledEdit2: TLabeledEdit;
    StaticText1: TStaticText;
    StaticText2: TStaticText;
    procedure OnCalcBtnClick(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses Unit2;

type TMyCalcFunc = function(a,b : double) : double of object;

procedure TForm1.OnCalcBtnClick(Sender: TObject);
var
  MyCalc     : TMyCalc;
  MyCalcFunc : TMyCalcFunc;
  Method: TMethod;
begin

  MyCalc := TMyCalc.Create;
  try
    //Method.Data := MyCalc;
    if TButton(Sender).Caption = 'Add' then
    begin
      MyCalcFunc := MyCalc.Add;
    end
    else
    begin
      MyCalcFunc := MyCalc.Subtract;
    end;
    StaticText2.Caption := FloatToStr(MyCalcFunc(StrToFloat(LabeledEdit1.Text),StrToFloat(LabeledEdit2.Text)));
  finally
    MyCalc.Free;
  end;

end;

end.


【メソッドポインタ経由で呼び出されるクラスのサンプル】


unit Unit2;

interface

  type TMyCalc = class
    function Add(a,b : double) : double;
    function Subtract(a,b : double) : double;
  end;

implementation

{ TMyCalc }

function TMyCalc.Add(a, b: double): double;
begin
  Result := a + b;
end;

function TMyCalc.Subtract(a, b: double): double;
begin
  Result := a - b;
end;

end.


メソッドポインタはヘルプにもあるように、

Type 型名 = "メソッドの定義" of object

のように宣言します。

ここで、"メソッドの定義"は、通常の手続き(関数)の名前を抜いたものになるので、
例えば、TObject型のSenderを引数に持ち、戻り値がない"メソッドの定義"は、

procedure(Sender : TObject)

同様に、Double型のaとbを引数に持ち、Double型の戻り値がある"メソッドの定義"は

function(a,b : Double) : Double

となります。

上記のサンプル1では、ボタンのキャプションに応じてif分で関数を切り替えています。

この例では、関数が2つだけなので、メソッドポインタ経由ではなく、直接目的の関数を
コールしたほうが良いのですが、
同じ型の引数を持つ関数が多数ある場合、メソッドポインタと、TObject.MethodAddressを
組み合わるとコード量を減らせる可能性があります。(上の例だとボタンのCaptionと関数名を
合わせおくことによりif文(あるいは、Case文)を無くすことが可能です。)

そのへんの話はまた後日・・・




0 件のコメント: