Mixin

MixinまたはMix-in（ミックスイン）は、オブジェクト指向プログラミングで用いられる技法であり、他のクラスから使用されるメソッド群を持つクラスが、他のクラスのスーパークラスにならないで済むための、特別な多重継承関係を実現するためのメカニズムを意味している。Mix-inされたメソッドに、他のクラスがアクセスする方法はそれぞれの言語仕様に依存している。 Mix-inはコードの再利用性を促進し、従来のクラスの多重継承がもたらしていた菱形継承などの数々の問題を回避する。多重継承を採用していない言語においては、多重継承と類似の機能性をより堅牢にして提供する。依存性逆転の原則のデザインパターンにも応用されている。 Mix-inの理念は、クラスに機能を注入することである。機能ユニットをクラス（Mix-inクラス）として表現して、それを他のクラスにミックスできるようにすることである。機能ユニットはメソッドの集合体にされることが多い。Mix-inは、UMLクラス図にある汎化/特化および実現/実装の双方に該当しない継承の種類を表わしている概念であり、それはニーズ/インクルード（need/include）とも言われる。Mix-inの各言語での導入方法は非常に多様化しているので、その用法は曖昧である。 Mix-inクラスは、多重継承されることを前提にして、上位クラスのように振る舞って自身が内包する機能性を提供し、下位クラスはその機能性を利用する権利を得るが、その特化の義務までは負わない。特化（specialization）とはUMLクラス図のそれであり、Is-a関係や派生（subtyping）がそれに該当している。Mix-inクラスの継承関係では、上位（super）基底（basic）よりも親（parent）、下位（sub）派生（derived）よりも子（child）と言った方が適当になる。 Mix-inクラスの代表的形態はトレイト（trait）である。トレイトの継承はインクルード（include）と言う方が好まれる。言語によってモジュール（module）プロトコル（protocol）ロール（roles）といった形態もあり、それぞれ微妙な機能の違いがある。Mix-inクラスと抽象クラスと具象クラスを一律化している言語もある。関数オブジェクトをトレイトとして扱える言語もある。型クラス（type class）をトレイト相当にしている言語もある。メソッド実装可能にしたインターフェースを事実上のトレイトにしてる言語もある。 Mix-inの利点は以下のようになる。 クラスの多重継承問題を回避しつつ、多様な機能性のみを利用できる。 Mix-inクラスによる機能の分類体系化によって、コードの再利用性を促進させる。 親クラスの特化の義務を負わずに、親クラスの機能をかいつまんで利用できる権利を得る。 Mix-inの欠点は以下のようになる。 Mix-inの多用は機能中心のプログラムを招いて、データ中心のオブジェクト指向の本質から外れる。 Mix-in設計は煩雑になりがちであり、UMLクラス図の汎化特化設計および実現実装設計よりも品質が低下する。 Mix-inではメソッド決定順序（MRO）がブラックボックス化しがちであり、結局これは多重継承問題と同類になる。 mixinは、そのようなもの自体はそれ以前からも考えられていたが、1970年代のMIT系Lisp方言のオブジェクト指向システムFlavors（英語版）でその名が使われ、それが一般化した。Flavorsは、同時期のSmalltalkのオブジェクト指向システムに影響された試みのひとつであるが多重継承を特長とした。名称の由来は、マサチューセッツ州 Somerville にあったアイスクリーム屋からヒントを得て考え出されたものであるこのアイスクリーム店の店長は（バニラやチョコレートなどの）基本となる味(Flavor)を混ぜ、追加の具材（ナッツ、クッキー、キャンディなど）と組み合わせたものを提供し、それを Mix-In と呼んで店の登録商標としていた。 mixinはコードの再利用を促進する。しかし、mixin にはそれなりの妥協も伴う。（クラスの多重継承すなわち実装の多重継承ができず、インタフェースの複数実装による型の多重継承のみができる、例えばJavaやC#などの観点からは）mixin は、「メソッド実装付きのインタフェース」ということもできる。クラスが mixin を含む場合、そのインタフェースを実装したクラスは、mixin の属性と操作を取り込む。継承するというのとは異なっている。取り込んだ要素はコンパイル時にクラスの一部となる。興味深いことに、mixin はインタフェースを実装する必要はない。それでもあえてインタフェースを実装する利点は、そのインタフェースを必要とするメソッドに、引数としてインスタンスを渡せるからである。 Mixinの原点は、MIT系Lisp方言オブジェクト指向システムのFlavors（英語版）であり、その後継であるCommon Lisp オブジェクトシステム（CLOS）上の実装で広く知られるようになっている。日の丸言語RubyもMixinの採用言語として有名である。Mixinを採用している言語としては以下のものがある。 Ada - 総称型パッケージの特殊ディスパッチがそれに相当する D言語 - テンプレート・ミックスインが導入されている Dart Groovy JavaScript - 関数オブジェクトがそれに相当する Kotlin OCaml Perl PHP MATLAB Python Racket Raku - ロールとして導入 Ruby - モジュールとして導入 Scala Smalltalk Swift - プロトコルとして導入 Vala Object REXX XOTcl（英語版） Strongtalk（英語版） Python の、特に Python 2.3 以降および Python 3 では C3 linearization により多重継承した際のメソッド探索順は解決されるので、多重継承は有力な手法であり、実際にいくつか活用例がある。SocketServer モジュールは UDP および TCP ソケットサーバとして動作する UDPServer と TCPServer クラスの両方を備えている。通常、すべてのコネクションは同じプロセス内で処理されるが、ForkingMixIn と ThreadingMixIn という追加の mixin クラスが存在する。下記のように TCPServer を ThreadingMixIn により拡張すると、 class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass ThreadingMixIn が TCPServer にコネクションごとにスレッドを生成する機能を追加する。あるいは、ForkingMixIn を用いると各新規のコネクションに対してプロセスが fork される。明らかに、スレッドを生成したりプロセスを fork する機能は単独では大して役に立たない。 この使用例では、mixin はソケットサーバとしての機能に影響することなく、基盤となる機能を選択可能な形で提供している。 C#ではインタフェースと拡張メソッドの組合せによって、Mix-inを再現できる。 using System.Linq; System.Collections.Generic.IEnumerable<int> range = Enumerable.Range(1, 10); // IEnumerable<T>にはSum()メソッドは定義されない。 // 実際にはSystem.Linq.Enumerableクラスに実装された拡張メソッドである。 int sum = range.Sum(); // 上記は下記の糖衣構文である。 int sum = Enumerable.Sum(range); トレイト 抽象型 Decoratorパターン デリゲーション 多重継承 アスペクト指向