2012年12月12日水曜日

関数のメソッドポインタ

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


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

  1. unit Unit1;  
  2.   
  3. interface  
  4.   
  5. uses  
  6.   Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,  
  7.   Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;  
  8.   
  9. type  
  10.   TForm1 = class(TForm)  
  11.     Button1: TButton;  
  12.     Button2: TButton;  
  13.     LabeledEdit1: TLabeledEdit;  
  14.     LabeledEdit2: TLabeledEdit;  
  15.     StaticText1: TStaticText;  
  16.     StaticText2: TStaticText;  
  17.     procedure OnCalcBtnClick(Sender: TObject);  
  18.   private  
  19.     { Private 宣言 }  
  20.   public  
  21.     { Public 宣言 }  
  22.   end;  
  23.   
  24. var  
  25.   Form1: TForm1;  
  26.   
  27. implementation  
  28.   
  29. {$R *.dfm}  
  30.   
  31. uses Unit2;  
  32.   
  33. type TMyCalcFunc = function(a,b : double) : double of object;  
  34.   
  35. procedure TForm1.OnCalcBtnClick(Sender: TObject);  
  36. var  
  37.   MyCalc     : TMyCalc;  
  38.   MyCalcFunc : TMyCalcFunc;  
  39.   Method: TMethod;  
  40. begin  
  41.   
  42.   MyCalc := TMyCalc.Create;  
  43.   try  
  44.     //Method.Data := MyCalc;  
  45.     if TButton(Sender).Caption = 'Add' then  
  46.     begin  
  47.       MyCalcFunc := MyCalc.Add;  
  48.     end  
  49.     else  
  50.     begin  
  51.       MyCalcFunc := MyCalc.Subtract;  
  52.     end;  
  53.     StaticText2.Caption := FloatToStr(MyCalcFunc(StrToFloat(LabeledEdit1.Text),StrToFloat(LabeledEdit2.Text)));  
  54.   finally  
  55.     MyCalc.Free;  
  56.   end;  
  57.   
  58. end;  
  59.   
  60. end.  


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

  1. unit Unit2;  
  2.   
  3. interface  
  4.   
  5.   type TMyCalc = class  
  6.     function Add(a,b : double) : double;  
  7.     function Subtract(a,b : double) : double;  
  8.   end;  
  9.   
  10. implementation  
  11.   
  12. { TMyCalc }  
  13.   
  14. function TMyCalc.Add(a, b: double): double;  
  15. begin  
  16.   Result := a + b;  
  17. end;  
  18.   
  19. function TMyCalc.Subtract(a, b: double): double;  
  20. begin  
  21.   Result := a - b;  
  22. end;  
  23.   
  24. 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 件のコメント: