株式会社豆蔵 取締役・プロフェッショナルフェロー
はじめに
前回はScala言語の特徴とクラス定義の仕方をJavaとの比較をしながら説明しました。今回はさらに突っ込んで,Scalaの文法的な特徴をミニツアーという形で探検していきたいと思います。
Javaのインターフェースに代わるtraitを用いるmixin型多重継承,型階層とコレクションの紹介をしていきます。
Traitでmix-in型の多重継承を
ScalaにはJavaのインターフェースにあたるものとしてtraitがあります。traitとは特質とか形質という意味の英語です。実はtraitはJavaのインターフェースよりも強力です。インターフェースと違い,属性や操作の実装(メソッドの中身)を定義することもできるからです。Scalaでは,traitを単一の目的機能に奉仕するモジュールの部品化に利用します。そのような部品群をミックスインして組み合わせることにより各アプリケーションで必要なニーズに応えていこうという発想でScalaは設計されているのです。
Scalaでは通常のクラスは単一継承しか認められていませんが,traitを多重継承(ミックスイン)することができ,結果として多重継承が実現できます。これは,Rubyのモジュールとほぼ同じ機能だと考えてよいでしょう。以下例を見てみます。ここではわかりやすさのために,traitの名前はTで始めるようにしています。traitはクラスを継承することでも他のtraitを継承することでも定義できます。
class Person ; //実験用の空クラス(前回のPersonクラスを使う場合は,
//以下のPianoplayingTeacherにコンストラクタ引数が必要)
trait TTeacher extends Person {
def teach //実装を伴わないバーチャルなメソッド
}
trait TPianoPlayer extends Person {
def playPiano = {println(“I’m playing piano. “)} //実装を伴う具象メソッド
}
class PianoplayingTeacher extends Person with TTeacher with TPianoPlayer {
def teach = {println(“I’m teaching students. “)} //操作teachの実装を定義
}
このように,traitはwith節を何個も連ねて複数のtraitをmixinしたクラスを定義することができるわけです。1個目の継承元はextendsで指定し,2個目以降はwith節で指定します。もうおわかりのように,インスタンスを生成可能なのはabstractでないクラスのみです。traitから直接インスタンス生成はできないことに気をつけてください。
では実際に実行してみましょう。
scala> val t1 = new PianoplayingTeacher
t1: PianoplayingTeacher = PianoplayingTeacher@1e26d42
scala> t1.playPiano
I'm playing piano.
scala> t1.teach
I'm teaching students.
実は,インスタンス生成時にそのオブジェクトに対して個別にtraitの性質を与えることもできます。
scala> val tanakaTaro = new Person with TTeacher with TPianoPlayer { def teach = {println("I'm teaching students.")} }
tanakaTaro: Person with TTeacher with TPianoPlayer = $anon$1@13b8f62
scala> tanakaTaro teach
I'm teaching students.
scala> tanakaTaro playPiano
I'm playing piano.