2012年12月13日木曜日

publishedなメソッドを隠す(ネストした型宣言使用編)

前回の続きです。

さて、最近のDelphiでは、ネストした型宣言が可能で、クラス宣言の中にクラスの宣言ができます。

この機能を使って、クラスの使用者からpublishedなメソッドを隠すことを試してみました。

以下、ソースです。

先ず、 【関数名でメソッドが呼び出されるクラスのサンプル】

unit Unit2;

interface

  type TMyCallCalc = class
    public
      function CallCalc(CalcName : string; a, b: double) : double;
    private
      type TMyCalc = class
        published
          function Add(a,b : double) : double;
          function Subtract(a,b : double) : double;
      end;

  end;


implementation
{ TMyCalc }

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

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


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

function TMyCallCalc.CallCalc(CalcName : string; a, b: double) : double;
var
  MyCalc     : TMyCalc;
  MyCalcFunc : TMyCalcFunc;
  MethodVar : TMethod;
begin

  MyCalc := TMyCalc.Create;
  try
    MethodVar.Data := MyCalc;
    MethodVar.Code := MyCalc.MethodAddress(CalcName);


    if Assigned(MethodVar.Code) then
    begin
      MyCalcFunc := TMyCalcFunc(MethodVar);
      Result := MyCalcFunc(a,b);
    end;
  finally
    MyCalc.Free;
  end;

end;

end.

親クラスのprivateセクションにpublishedなメソッドを持つ子クラスを宣言しています。
これで、ユニットの使用者からは、子クラスのメソッドの宣言が見えなくなり、直接呼び出す
ことができなくなります。
ユニットの使用者には、publicセクションにメソッドを宣言することで、間接的に目的の
メソッドが呼び出せるようにします。

次に上記のクラスを使用するコード


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;

procedure TForm1.OnCalcBtnClick(Sender: TObject);
var
  CallCalc : TMyCallCalc;
begin
  CallCalc := TMyCallCalc.Create;
  try
    StaticText2.Caption := FloatToStr(CallCalc.CallCalc(
                                    TButton(Sender).Caption,
                                    StrToFloat(LabeledEdit1.Text),
                                    StrToFloat(LabeledEdit2.Text)));
  finally
    CallCalc.Free;
  end;

end;

end.

ユニットを使用する側からは子クラスが見えませんので、親クラスのpublicなメソッドのみが
使用できます。



0 件のコメント: