Scala ひと巡り : ミックスインクラス合成 (Mixin Class Composition)

単一継承のみをサポートする言語と対照して、Scala には、クラス再利用のためのより汎用的な概念があります。Scala では、クラスの新しいメンバー定義(すなわち、スーパークラス継承の差分)を再利用できます。これはミックスインクラス合成として表現されます。イテレー タに関する次の抽象化を考えてみます。

abstract class AbsIterator { type T def hasNext: Boolean def next: T }

次に、メソッド foreach を用いて AbsIterator を展開するミックスインクラスについて考えます。ここで foreach は、イテレータが返す各要素に与えられた関数を適用します。ミックスインとして使用できるクラスを定義するのに、キーワード trait を使います。

trait RichIterator extends AbsIterator { def foreach(f: T => Unit) { while (hasNext) f(next) } }

次は、与えられた文字列の文字を次々に返す、具象イテレータクラスです:

class StringIterator(s: String) extends AbsIterator { type T = Char private var i = 0 def hasNext = i < s.length() def next = { val ch = s charAt i; i += 1; ch } }

StringIterator と RichIterator の機能を 1 つのクラスへ統合したいとします。これは単一継承とインタフェースだけではできません。両クラスともコードを伴うメンバー実装を含むからです。Scala では、ミックスインクラス合成を使ってできます。プログラマはクラス定義の差分 --- すなわち、継承さていれないすべての新しい定義 --- を再利用できます。この機構により、次のテストプログラムのようにして、RichIterator と StringIterator を統合できます。次は、与えられた文字列のすべての文字のカラムを印字します。

object StringIteratorTest { def main(args: Array[String]) { class Iter extends StringIterator(args(0)) with RichIterator val iter = new Iter iter foreach println } }

関数 main 中の Iter クラスは、親の StringIterator と RichIterator をキーワード with を使ってミックスイン合成し、構築されています。最初の親は Iter のスーパークラスと呼ばれるのに対し、2 つめ(と、もしあればその他すべて)の親は、ミックスインと呼ばれます。