第9章：Scalaのトレイト(trait)

今回はトレイトについて語ってみるよ。
トレイトがわかると実装の可能性が広がるから、やってみよう！

# Scalaのトレイト
まずは __トレイト__ の感じを掴んでみYO！

色々な意見があるかもしれないけど、トレイトをこういうモノだと思っている。

__機能を切りだして、再利用可能な塊にしたモノ__

トレイトはJavaのインタフェース(interface)に近いモノという説明もある。
確かに、Javaのインタフェースのように使えると思うんだけど
なんかスッと入ってこないんだよね。
まだまだScalaの修業が足りないせいかもしれない。

## トレイトの特徴
Scalaのトレイトには、以下な大きな特徴があるよ。

- traitキーワードで定義
- クラスパラメータを取ることができない
- メソッドを実装できる
- クラスや他のトレイトにミックスインできる
- 任意の数をミックスインできる
- 純粋ではないが多重継承ぽさがある

この特徴に沿って説明してみるね。

## traitキーワードで定義
早速トレイトを定義してみよう。

    scala> trait Job
    defined trait Job

なんと、これだけでJobというトレイトが定義できてしまった。
トレイトを作ることはもう簡単だね！

## クラスパラメータを取ることができない
クラスは以下のようにクラスパラメータを定義できるよね？

    scala> class Job(name: String)
    defined class Job

同じことをトレイトでやってみると

    scala> trait Job(name: String)
    <console>:1: error: traits or objects may not have parameters
           trait Job(name: String)
                    ^

コンパイルエラーが発生してしまうんだ。
これってつまりは、パラメータによる初期化ができないってことなんだよね。

でもこんな感じで、パラメータを受け取って初期化できるよ。

    scala> trait Job { val name: String }
    defined trait Job
    
    scala> new Job { val name = "student" }
    res0: Job = $anon$1@518677ee
    
    scala> res0.name
    res1: String = student

もう1つ。

    scala> trait Job { val name: String }
    defined trait Job
    
    scala> new { val name = "student" } with Job
    res2: Job = $anon$1@701ce28a
    
    scala> res2.name
    res3: String = student



## メソッドを実装できる
次にメソッドを追加してみるよ。

```scala:Human.scala
trait Job {
  def getName() {
    "student"
  }
}
```

どう？Javaのインタフェースでは、`getName`メソッドのように実装を持つことはできないよね。
もうこの時点でJavaのインタフェースとの違いが出てきていました。

これが、機能を切り出すために実現されているコトの1つだよ。

## クラスや他のトレイトにミックスインできる
トレイトを使うところを見たい！ってなってきていますよね？
今度は、トレイトを使ってみるよ。
ここで __ミックスイン__ が出てくるんだ。

### ミックスイン
ミックスインとは、 __複数のトレイトを使ってクラスやトレイトを定義する__ ことだ。
このことを __ミックスイン合成__ なんて言うこともある。
Javaのインタフェースで言うと、 __複数のインタフェースを実装してクラスを定義する__ みたいな。

クラスやトレイトを定義するために __使用したトレイト__ のことをミックスインと言うこともある。

この辺、言語によっても違うみたいだし、捉え方によっても違うから難しいところだけど、
ここでは上記のような整理にするよ。

### ミックスインしてみる
やってみるよ！

```scala:Trait1.scala
object Trait1 {
  def main(args: Array[String]){
    val man = new Man
    man.say()
  }
}

trait Human {
  val name = "飛行帽"

  def sayName() {
    println("My name is " + name)
  }
}

class Man extends Human
```
ここでは、HumanトレイトをミックスインしてクラスManを作っている。
ここではミックスインする時に、`extends`を使っている。
実は`extends`か`with`キーワードでミックスインする。

- `extends`の場合は、他のクラスを継承しない場合に使用する。指定したトレイトのスーパークラスが暗黙の継承クラスとなる。スーパークラスが存在しない場合は、`AnyRef`クラスとなる。1つしか指定できないため、その他のトレイトは`with`で指定する。
- `with`の場合は、`extends`を指定済みで、他のトレイトを指定する場合に使用する。

## 任意の数をミックスインできる
もう先に書いたけど、`with`キーワードを使って複数のトレイトをミックスインすることもできるんだ。

```scala:Trait2.scala
object Trait2 {
  def main(args: Array[String]){
    val man = new Man("虎丸龍次", "男塾", "一号生")
    man.say()
  }
}

trait Human {
  val name: String
}

trait Job {
  val job: String
}

trait Grade {
  val grade: String
}

class Man(n: String, j: String, g: String) extends Human with Job with Grade {
  val name = n
  val job = j
  val grade = g

  def say() {
    println("名前は" + this.name + "じゃ。" + job + grade + "じゃ。")
  }
}
```

##  純粋ではないが多重継承ぽさがある
Scalaの継承は、単一継承のみで多重継承はサポートしていないんだ。
でもトレイトを使うと、多重継承ぽくできるみたいなんだ。

ここはゴメンナ。
実は多重継承をやったことないから、イメージがわかないんだ。

# まとめ
今回は、 __トレイト__ について語ってみたけど、掴むことができたかな？
もちろんトレイトにもまだまだ色々あるから調べてね。

トレイトを使いこなすには、モデリングとデザインの部分も重要だと思うよ。

今回も
__体で感じてくれたかな？__