人気ブログランキング | 話題のタグを見る

ダック・タイピング

ダック・タイピングという言葉を聞いたことがあるだろうか。Rubyなどのオブジェクト指向言語に現れる現象らしい。ウィキペディアでは次のような説明がしてあった。
ダック・タイピング(duck typing)とは、Smalltalk、Python、Rubyなどのいくつかの動的型付けオブジェクト指向プログラミング言語に特徴的な型付けの作法のことである。それらの言語ではオブジェクト(変数の値)に何ができるかはオブジェクトそのものが決定する。つまり、オブジェクトがあるインタフェースのすべてのメソッドを持っているならば、たとえそのクラスがそのインタフェースを宣言的に実装していなくとも、オブジェクトはそのインタフェースを実行時に実装しているとみなせる、ということである。それはまた、同じインタフェースを実装するオブジェクト同士が、それぞれがどのような継承階層を持っているのかということと無関係に、相互に交換可能であるという意味でもある。

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

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

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

デーブ・トーマスはRubyコミュニティで初めてこの言葉を使ったと考えられている。
Wikipediaに出ていた例を irb で検証してみた。

irb(main):001:0> def test(foo)
irb(main):002:1> puts foo.sound
irb(main):003:1> end
=> nil
irb(main):004:0> class Duck
irb(main):005:1> def sound
irb(main):006:2> 'quack'
irb(main):007:2> end
irb(main):008:1> end
=> nil
irb(main):009:0> class Cat
irb(main):010:1> def sound
irb(main):011:2> 'myaa'
irb(main):012:2> end
irb(main):013:1> end
=> nil
irb(main):014:0> test(Duck.new)
quack
=> nil
irb(main):015:0> test(Cat.new)
myaa

ポイントは test 関数が引き数にオブジェクトをとっていること。Duck クラスと Cat クラスは全く別物であるのに、つまり、継承関係もないのに、その定義の中で sound という同じ名前のメソッドを持っているために、それらのオブジェクトはいずれも test 関数の引数になって正常に動作できるということだ。アヒルのように歩いて、アヒルのように鳴くオブジェクトはアヒルとして取り扱って良いということだ。

関数がオブジェクトを引き数としてとり、そのオブジェクトのメソッドを使って定義されている場合、同じ名前のメソッドを持っていれば、どんなオブジェクトもその関数の引き数として利用することができる。この関数の引き数の型はコンパイル時には決まっておらず、動作時に変化する。このような引き数の型を、ダック・タイピングというらしい。

ダック・テストというのは英米でよく使われるアナロジーで、見かけと本質は違うという議論に対し、本質は見かけのとおりだとする考え方らしい。

48時間でSchemeを書こう』の途中で、いきなりダック・タイピングの話になってしまったが、これは、『48時間でSchemeを書こう』の次の記事が、Haskell のGHC拡張である存在型の話だからだ。存在型とダック・タイピングとどんな関係があるのかと思うかもしれないが、関係があるらしい。

実は『48時間でSchemeを書こう』というチュートリアルを『銀の匙方式』で読んでみたくなったのだ。つまり、わからないと思ったら徹底的に脱線するということだ。どこまで脱線できるのか分からないが、できるだけわかったつもりをなくそうと思う。
by tnomura9 | 2011-12-21 18:47 | Haskell | Comments(0)
<< 存在型 (Existentia... galaxias! >>