普段何気なく使っている技術や言葉について、表面的な知識にせず、しっかりとイメージできるまで自分なりに調べて整理し、理解するシリーズ。
ダックタイピングとは
ダックタイピングとは、Rubyなどの動的型付けオブジェクト指向プログラミング言語で使われる型付けのやり方のことです。
この名前は「もしオブジェクトがダックのように鳴き、ダックのように歩くのならば、そのクラスが何であれ、それはダックである」と言う表現に由来しています。つまり、その何かが穴を掘ろうが、ジャンプしようが、ダックのように鳴き、歩くのであれば、それはダックとして扱うことができるということだと解釈しました。
実際にコードに落とし込んで考えた際、ダックタイプはどの特定のクラスとも紐付かないインタフェースを定義することになると考えました。
ダックタイピングの使い所と具体例
実際にRubyでダックタイピングの使い所を考えてみます。
具体例として特典クラスがあり、会員によって提供する特典が変わるとします。会員を引数にcase文を使って提供する特典を判定しています。
この状態だと、会員メンバーのランクが増える度に、case文を追加しなくてはならず、システムが複雑化していく要因になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Benefit attr_reader :gift_certificate, :souvenir, :coupon def find_benefit(members) members.each do |member| case member when PlatinumMember employee.prepare_gift_certificate(gift_certificate) when GoldMember employee.prepare_souvenir(souvenir) when StandardMember employee.prepare_coupon(coupon) end end end |
ダックタイプを意識して設計し直すと、以下のようになります。それぞれの引数のクラスは、新しいインターフェースを実装しています。
また、それぞれのランククラスが応答できるfind_benefitを追加することで、オブジェクトごとに振る舞いを変えることができます。
このprepare_benefitメソッドは、新たにランクを追加した際でも変更されることがありません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class Benefit attr_reader :gift_certificate, :souvenir, :coupon def prepare_benefit(members) members.each do |member| member.find_benefit(self) end end end class PlatinumMember def find_benefit(benefit) prepare_gift_certificate(benefit.gift_certificate) end end class GoldMember def find_benefit(benefit) prepare_souvenir(benefit.souvenir) end end class StandardMember def find_benefit(benefit) prepare_coupon(benefit.coupon) end end |
ダックタイピングとポリモーフィズムの関係性
ダックタイピングを学んでみて、真っ先に思い浮かんだのはポリモーフィズムでした。ポリモーフィズムはあるが、ダックタイピングがないJavaなどの言語もあり、ダックタイピングはポリモーフィズムを実践するための一つの手段のように思いました。
実際に本記事の参考である、「オブジェクト指向設計実践ガイド」でもポリモーフィズムの話が登場し、一つの方法と説いています。
とはいえ、ダックタイピングとポリモーフィズムの関係性について調べていると、ポリモーフィズムはインターフェースによる明示性を必要をするものだからダック・タイピングは違うと説いている意見もあり、若干混乱しています。。
ダックタイピングというより動的型付け言語における課題点
ダックタイピングを学んで、より動的型付け言語における型による実行時エラーの課題点が浮き彫りになったように思いました。
ダックタイピングはオブジェクト指向設計における柔軟性と変更のしやすさを高めるが、静的型付け言語のように型を明確に定義しないが故に、実行するまで型エラーに気づくことが難しい点があります。特に大規模の開発や複雑なシステムにおいて大きな障害になるのではないかと思いました。
参考: