Mixin
MixinまたはMix-in(ミックスイン)は[1][2][3][4]、オブジェクト指向プログラミングで用いられる技法であり、他のクラスから使用されるメソッド群を持つクラスが、他のクラスのスーパークラスにならないで済むための、特別な多重継承関係を実現するためのメカニズムを意味している。Mix-inされたメソッドに、他のクラスがアクセスする方法はそれぞれの言語仕様に依存している。
Mix-inはコードの再利用性を促進し、従来のクラスの多重継承がもたらしていた菱形継承などの数々の問題を回避する[5]。多重継承を採用していない言語においては、多重継承と類似の機能性をより堅牢にして提供する。依存性逆転の原則のデザインパターンにも応用されている。
概要
Mix-inの理念は、クラスに機能を注入することである。機能ユニットをクラス(Mix-inクラス)として表現して、それを他のクラスにミックスできるようにすることである[6]。機能ユニットはメソッドの集合体にされることが多い。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の利点は以下のようになる。
- クラスの多重継承問題を回避しつつ、多様な機能性のみを利用できる[7]。
- Mix-inクラスによる機能の分類体系化によって、コードの再利用性を促進させる[8]。
- 親クラスの特化の義務を負わずに、親クラスの機能をかいつまんで利用できる権利を得る[9]。
Mix-inの欠点は以下のようになる。
- Mix-inの多用は機能中心のプログラムを招いて、データ中心のオブジェクト指向の本質から外れる。
- Mix-in設計は煩雑になりがちであり、UMLクラス図の汎化特化設計および実現実装設計よりも品質が低下する。
- Mix-inではメソッド決定順序(MRO)がブラックボックス化しがちであり、結局これは多重継承問題と同類になる。
来歴
mixinは、そのようなもの自体はそれ以前からも考えられていたが、1970年代のMIT系Lisp方言のオブジェクト指向システムFlavorsでその名が使われ、それが一般化した。Flavorsは、同時期のSmalltalkのオブジェクト指向システムに影響された試みのひとつであるが多重継承を特長とした。名称の由来は、マサチューセッツ州 Somerville にあったアイスクリーム屋[10]からヒントを得て考え出されたものである[11]このアイスクリーム店の店長は(バニラやチョコレートなどの)基本となる味(Flavor)を混ぜ、追加の具材(ナッツ、クッキー、キャンディなど)と組み合わせたものを提供し、それを Mix-In と呼んで店の登録商標としていた[12]。
mixinはコードの再利用を促進する。しかし、mixin にはそれなりの妥協も伴う。(クラスの多重継承すなわち実装の多重継承ができず、インタフェースの複数実装による型の多重継承のみができる、例えばJavaやC#などの観点からは)mixin は、「メソッド実装付きのインタフェース」ということもできる。クラスが 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
Mixinの例
Python
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#
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);
関連項目
脚注
- ^ Using Mix-ins with Python
- ^ Mix-Ins (Steve's ice cream, Boston, 1975) Archived 2007-10-26 at the Wayback Machine.
- ^ Implementing Mix-ins with C# Extension Methods
- ^ I know the answer (it's 42) : Mix-ins and C#
- ^ Boyland, John; Giuseppe Castagna (26 June 1996). “Type-Safe Compilation of Covariant Specialization: A Practical Case”. In Pierre Cointe. ECOOP '96, Object-oriented Programming: 10th European Conference. Springer. pp. 16–17. ISBN 9783540614395 17 January 2014閲覧。
- ^ http://c2.com/cgi/wiki?MixIn
- ^ http://culttt.com/2015/07/08/working-with-mixins-in-ruby/
- ^ http://naildrivin5.com/blog/2012/12/19/re-use-in-oo-inheritance.html
- ^ “Archived copy”. 2015年9月25日時点のオリジナルよりアーカイブ。2015年9月16日閲覧。
- ^ Steve's Ice Cream Parlor
- ^ Using Mix-ins with Python
- ^ LISTSERV 14.4
外部リンク
- Wiki entry at Cunningham & Cunningham, Inc.
- Mixins in ActionScript.
- Scala Overview: Mixin Class Composition - a step-by-step example in Scala
- The Common Lisp Object System: An Overview by Richard P. Gabriel and Linda DeMichiel provides a good introduction to the motivation for defining classes by means of generic functions.