これがduck typingか……?

ホットみたいですのでhttp://d.hatena.ne.jp/Cryolite/20060108#p1の例をAdaにしてみました。

with Ada.Finalization;
generic
   type Base_Type is abstract tagged limited private;
package dsp is

   type Dynamic_Scoped_Ptr is limited private;

   function Element (Object : Dynamic_Scoped_Ptr) return not null access Base_Type'Class;

   generic
      type Derived_Type is new Base_Type with private;
      with procedure Finalize (Object : in out Derived_Type) is <>;
   function Constructor (Data : not null access Derived_Type) return Dynamic_Scoped_Ptr;

private

   type Data_Access is access all Base_Type'Class;

   type Finalizer is abstract tagged null record;
   procedure Finalize (Object : in Finalizer; Data : in out Data_Access) is abstract;

   type Finalizer_Access is access all Finalizer'Class;

   type Dynamic_Scoped_Ptr is new Ada.Finalization.Limited_Controlled with record
      Data : Data_Access;
      Finalizer : Finalizer_Access;
   end record;
   overriding procedure Finalize (Object : in out Dynamic_Scoped_Ptr);

end dsp;
with Ada.Unchecked_Deallocation;
package body dsp is
   procedure Free is new Ada.Unchecked_Deallocation (Finalizer'Class, Finalizer_Access);
   function Element (Object : Dynamic_Scoped_Ptr) return not null access Base_Type'Class is
   begin
      return Object.Data;
   end Element;
   function Constructor (Data : not null access Derived_Type) return Dynamic_Scoped_Ptr is
      type Derived_Finalizer is new Finalizer with null record;
      overriding procedure Finalize (Object : in Derived_Finalizer; Data : in out Data_Access) is
         pragma Unreferenced (Object);
         type Derived_Access is access all Derived_Type;
         procedure Free is new Ada.Unchecked_Deallocation (Derived_Type, Derived_Access);
         D_Var : Derived_Type renames Derived_Type (Data.all);
         D_Var_Access : Derived_Access := D_Var'Access;
      begin
         Finalize (D_Var);
         Free (D_Var_Access);
      end Finalize;
      D_Fin : constant access Derived_Finalizer := new Derived_Finalizer;
      pragma Suppress (Accessibility_Check);
   begin
      return (Ada.Finalization.Limited_Controlled with Data_Access (Data), D_Fin.all'Unchecked_Access);
   end Constructor;
   overriding procedure Finalize (Object : in out Dynamic_Scoped_Ptr) is
   begin
      Finalize (Object.Finalizer.all, Object.Data);
      Free (Object.Finalizer);
   end Finalize;
end dsp;
with dsp;
with Text_IO;
procedure Test is
   type Base is abstract tagged limited null record;
   type Derived_1 is new Base with null record;
   procedure Finalize (Object : in out Derived_1) is
   begin
      Text_IO.Put_Line ("Close 1");
   end Finalize;
   type Derived_2 is new Base with null record;
   procedure Finalize (Object : in out Derived_2) is
   begin
      Text_IO.Put_Line ("Close 2");
   end Finalize;
begin
   declare
      package p is new dsp (Base);
      function ctor is new p.Constructor (Derived_1);
      function ctor is new p.Constructor (Derived_2);
      ptr1 : p.Dynamic_Scoped_Ptr := ctor (new Derived_1);
      ptr2 : p.Dynamic_Scoped_Ptr := ctor (new Derived_2);
   begin
      null;
   end;
end Test;

C++との違いは、genericのインスタンス化を明示的にしかできないため、newとは別に、p.Constructorをインスタンス化するところでDerived_1やDeriver_2の型名を書かなければならないところぐらいと思うのですが、これをduck typingと呼ぶのは違和感があるようなないような。単なるラッパーでは……。
私がduck typingを、折角クラス単位に閉じ込めたメソッドのスコープを再びグローバルなものにしてしまうあまり嬉しくない機能としか思ってないのも違和感の原因かも。非侵入的といっても、特定のメソッドについて名前を拘束してしまう時点で侵入してるわけですよ。同名同シグネチャのメソッドを要求する他の用途と被ってしまったら、スコープも何も無いわけで。
まあAdaなら回避できますがねっ!(←これが言いたかっただけ)

type Derived_3 is new Base with null record;
procedure Finalize (Object : in out Derived_3); -- 別の用途に使用
procedure Close (Object : in out Derived_3) is -- 終了処理はこっち
...
function ctor is new p.Constructor (Derived_3, Finalize => Close); -- 明示的にCloseを渡す

話題そのものについては、それ型クラスでできるよ派や、それMixJuiceでできるよ派や、関数ポインタ渡した方がマシだろう派の登場が期待されます。個人的にはVMT弄ってinterfaceを後付けで実装するテクニックが一番役に立つよ派を応援しています。