Delphiの無名メソッド型はインターフェース!?

スマートポインタ、使ってる? – 全力わはー」のエントリーを読んで、ソースコードの

type
  Auto<T: class> = reference to function: T;
  TAuto<T: class> = class(TInterfacedObject, Auto<T>)
    …

のところがわからなかったので調べてみました。

無名メソッドとは

無名メソッドは、名前のない手続き・関数です。

「reference to procedure」型や「reference to function」型の変数に代入できます。

以下のコードは、「reference to procedure」型の変数に無名メソッドを代入して使用する例です。

type
  TFuncOfPrint = reference to procedure(S: string);
var
  Func: TFuncOfPrint;
begin
  Func := procedure(S: string)
  begin
    WriteLn(S);
  end;

  Func('Hello world!');
end.

詳しくはdocwikiの「無名メソッド – RAD Studio」をご覧ください。

無名メソッドはインターフェース

無名メソッド型はインターフェースとして実装されています。

次のDelphiのコードをC++Builderでコンパイルすると

type
  TFunc<T> = reference to function: T;
  TProc<T> = reference to procedure(Value: T);

このようなコードが生成されます。

template<typename T> __interface TFunc__1  : public System::IInterface 
{
public:
    virtual T __fastcall Invoke(void) = 0 ;
};

template<typename T> __interface TProc__1  : public System::IInterface 
{
public:
    virtual void __fastcall Invoke(T Value) = 0 ;
};

つまり

type
  TFunc<T> = reference to function: T;

は、

type
  TFunc<T> = interface
    function Invoke(): T;
  end;

と同じ考えて良さそうです。

無名メソッドを継承する

インターフェースであることから、継承も可能です。

type
  TFunc<T> = reference to function: T;

  TFunc2<T> = interface(TFunc<T>)
  end;

  TFunc3<T> = class(TInterfacedObject, TFunc<T>)
  public
    function Invoke(): T;
  end;

無名メソッド型の変数に代入もできます。

type
  TFunc<T> = reference to function: T;

  TFunc3<T> = class(TInterfacedObject, TFunc<T>)
  private
    FValue: T;
  public
    constructor Create(Value: T);
    function Invoke(): T;
  end;

constructor TFunc3<T>.Create(Value: T);
begin
  FValue := Value;
end;

function TFunc3<T>.Invoke: T;
begin
  Result := FValue;
end;

var
  Func: TFunc<Integer>;
begin
  Func := TFunc3<Integer>.Create(100);
  WriteLn(Func);
end.

さいごに

スマートポインタ便利そうですね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください