メインメニューを開く

ダック・タイピングduck typing)とは、SmalltalkPerlPythonRubyなどのいくつかの動的型付けオブジェクト指向プログラミング言語に特徴的な型付けの作法のことである。それらの言語ではオブジェクト(変数の)に何ができるかはオブジェクトそのものが決定する。これによりポリモーフィズム(多態性)を実現することができる。つまり、静的型付け言語であるJavaC#の概念で例えると、オブジェクトがあるインタフェースのすべてのメソッドを持っているならば、たとえそのクラスがそのインタフェースを宣言的に実装していなくとも、オブジェクトはそのインタフェースを実行時に実装しているとみなせる、ということである。それはまた、同じインタフェースを実装するオブジェクト同士が、それぞれがどのような継承階層を持っているのかということと無関係に、相互に交換可能であるという意味でもある。

この用語の名前は「ダック・テスト」に由来する。

"If it walks like a duck and quacks like a duck, it must be a duck"

(もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルに違いない)

デーブ・トーマスはRubyコミュニティで初めてこの言葉を使ったと考えられている。

C++テンプレートはダック・タイピングの静的版である。例えば、STLにおける各種のiteratorはIterator基底クラスのようなものからメソッドを継承しているわけではないが、同じ構文でコンパイルが通るならば、それはiteratorの一種として扱える。この文脈で言う「同じインタフェースを持つ」とは、コンパイラにとってシグネチャなどのインタフェースが同じだということである。したがって、iteratorの実装はオブジェクトである必要すらない。

もう1つ、ダック・タイピングに似たアプローチにOCamlのstructural subtypingがある。メソッドのシグネチャが互換ならば、宣言上の継承関係は関係なくとも、オブジェクトの型は互換であるというものである。これはOCamlの型推論システムによってコンパイル時にすべて決定される。

目次

Rubyでの例編集

Rubyでの単純な例を示す。

 def test(foo)
   puts foo.sound
 end
 
 class Duck
   def sound
     'quack'
   end
 end
 
 class Cat
   def sound
     'myaa'
   end
 end
 
 test(Duck.new)
 test(Cat.new)

出力は以下である。

quack
myaa

2つのクラスに継承の関係が無いことに注目して欲しい。

C++での例編集

上記Rubyの例をC++で記述すると、以下のようになる。

 #include <iostream>
 
 template <class T>
 void test(const T& t) {
   std::cout << t.sound() << std::endl;
 }
 
 struct Duck {
   const char* sound() const {
     return "quack";
   }
 };
 
 struct Cat {
   const char* sound() const {
     return "myaa";
   }
 };
  
 int main() {
   test(Duck());
   test(Cat());
 }

実行結果はRubyの例と同じである。ただし、テンプレートによるダック・タイピングはコンパイル時に解決される静的なポリモーフィズムであり、動的型付け言語とは異なり実行時のオーバーヘッドを伴わない。

C#での例編集

C#はバージョン4.0で動的型付けを可能にするdynamic型が使えるようになった。dynamicは内部的にはリフレクションを利用して実装されており、該当するメソッドやプロパティの存在有無を実行時に遅延評価する。

using System;

class Duck {
    public string Sound() {
        return "quack";
    }
}

class Cat {
    public string Sound() {
        return "myaa";
    }
}

public class DuckTypingTest {
    static void Test(dynamic obj) {
        Console.WriteLine(obj.Sound());
    }

    public static void Main() {
        Test(new Duck());
        Test(new Cat());
    }
}

なお、C#はC++のテンプレートに似た機能としてジェネリクスをサポートするが、C++テンプレートほどの柔軟性はなく、ダック・タイピングに使用することはできない[1]

その他の言語など編集

Javaは言語構文レベルで動的型付けをサポートしないが、リフレクションを用いることで、ダック・タイピング相当を実現できる。

COMにおいても、IDispatchインタフェース[2]を実装することで、ダック・タイピング相当を実現できる。

脚注編集

関連項目編集

外部リンク編集