第22章：Scalaの抽出子

今回は __抽出子__ だよ。

こいつを使えるようになると、更にパターンマッチが便利になるんだ。

こんな感じで進めてみるよ！

- [抽出子とは](#抽出子とは)
- [抽出子を使う](#抽出子を使う)
- [unapplySeqメソッド](#unapplySeqメソッド)
- [applyメソッド](#applyメソッド)
- [applyとunapplyの関係](#applyとunapplyの関係)
- [まとめ](#まとめ)

# <a name="抽出子とは">抽出子とは</a>
__`unapply`メソッドが定義されているオブジェクト__ のことです。 
定義としては簡単だね！

このメソッドの役割は、受け取ったインスタンスを分解して、 __何かを抽出する__ ことです。 
パターンマッチでこのメソッドが使われることが多いです。

# <a name="抽出子を使う">抽出子を使う</a>
早速使ってみよう！

## パターンマッチで使う

```scala:User.scala
import scala.Option

class User(private val firstname: String, private val lastname: String)

object User {

  def unapply(user: User) = Option((user.firstname, user.lastname))

  def main(args: Array[String]): Unit = {
    val user = new User("剛次", "赤石")

    user match {
      case User(firstname, lastname) => println(lastname + " " + firstname)
      case _ => println("Not user.")
    }
  }

}
```

実行してみよう！

```
$ scalac User.scala
$ scala  scala User
赤石 剛次
```

### 説明

まず`User`クラスを用意してみたぞ。

```scala
class User(private val firstname: String, private val lastname: String)
```

次に`User`クラスのコンパニオンオブジェクトを作り、この中に`unapply`メソッドを用意した。

```scala
object User {

  def unapply(user: User) = Option((user.firstname, user.lastname))
}
```

`unapply`メソッドの決め事は、以下みたいなんだ。

- 引数は、抽出対象のインスタンス
- 戻り値は、抽出したモノを`Option`で包む

今回引数は、コンパニオンクラスのインスタンスにしてみた。 
そして戻り値は、`fristname`と`lastname`にした。

最後に使う場所を`User`オブジェクトの`main`メソッドとして用意した。

```scala
  def main(args: Array[String]): Unit = {
    val user = new User("剛次", "赤石")

    user match {
      case User(firstname, lastname) => println(lastname + " " + firstname)
      case _ => println("Not user.")
    }
  }
```

生成した`User`インスタンスの`user`をパターンマッチすると、`case User(firstname, lastname)`で`User#unapply`が呼び出され、
抽出した値を変数`firstname`と`lastname`に束縛する。

こんな感じで __抽出子__ を使うことができるんだ。

## 代入で使う
こんな形でも使えるぜ！さっきの`User`クラスがいる前提でだからな！

```scala
object User1 {

  def main(args: Array[String]): Unit = {
    val user = new User("剛次", "赤石")
    val User(firstname, lastname) = user

    println(lastname + " " + firstname)
  }

}
```

先にパターンマッチで説明しちゃったけど、こっちの方が抽出子って感じがする。

__抽出子って使いようによっては可能性が広がるね！__

# <a name="unapplySeqメソッド">unapplySeqメソッド</a>
unapplyにSeqが付いてるメソッド。ということは、もしかして。。。 
そうです。可変長のオブジェクトからの抽出子となります。

Seqがついているのが気になったので、Scaladocで`Set`と`Map`を見てみた。やっぱり`unapply`と`unapplySeq`がいない。 
つまり順番で抽出することがわかるね。

あとはさらっと流すよ。

```scala
val seq = Seq(1, 2, 3, 4)
val Seq(x, y , _*) = seq
```

抽出して変数`x`, `y`に束縛したね。

# <a name="applyメソッド">applyメソッド</a>
基本編では`apply`メソッドについて触れていなかったので、ここで触れます。

まず以下のような`apply`メソッドを持つオブジェクトを用意する。

```scala
scala> object ApplyTest { def apply(message: String) { println(message) } }
```

このメソッドを呼び出すには、こうするよね？

```scala
scala> ApplyTest.apply("乱坊少佐")
乱坊少佐
```

でも`ApplyTest("乱坊少佐")`とするだけでも、`apply`メソッドを呼びすことが可能なんだ！

```scala
scala> ApplyTest("乱坊少佐")
乱坊少佐
```

いわゆる、シンタックスシュガー(糖衣構文)ってやつだね。

こういう使い方は少ないのかな？ファクトリーメソッド的な感じで使うことが多いみたいなんだ。 
例えばこんな感じ。

```scala
scala> class ApplyClass(val message: String); object ApplyClass { def apply(message: String): ApplyClass = { new ApplyClass(message) } }
defined class ApplyClass
defined module ApplyClass

scala> ApplyClass("乱坊少佐")
res0: ApplyClass = ApplyClass@43679ffd
```

まぁシンタックスシュガーということだけで、後は他のメソッドと変わらないからな！

ところで、今までもよく使っているオブジェクトがありました。それはなんでしょうか？

そうです。コレクション系です。軽く`Seq`オブジェクト`apply`メソッドについて見てみよう。

```scala
def apply[A](elems: A*): Seq[A]
```

`Seq[A]`を返している。つまり今まで

```scala
Seq(1, 2, 3)
```

なんて書いていたのは、`apply`メソッドを使っていたのです。

更にちなみに、引数の`elems: A*`は複数を表す。もちろん0個の場合もOK。 
正規表現の __直前の文字の0回以上の繰り返し__ と似ているね。

## ケースクラス
`apply`, `unapply`共通な話なので、ここに記載する。 
ケースクラスを作ると、`apply`, `unapply`メソッドが自動で実装されます。興味がある人は、見てみてね！

# <a name="applyとunapplyの関係">applyとunapplyの関係</a>
関係ありそうだよね？
まず、常に両方を定義する必要はありません。必要な方だけ定義すれば良いです。 
それは今までの例を見ればわかってもらえると思います。

両方を定義する場合はどうだろう？
実は __注入__ と __抽出__ の関係が存在している。

- __注入(injection)__
    -  `apply`メソッド
- __抽出(extraction)__
    - `unapply`メソッド

と考えるんだ。
抽出は __何か__ を抽出し、注入は __何か__ を注入する。 __何か__ を共通の存在にできるね。

必ずこの関係性を満たす必要はないけど、なるべく満たした方が良いなんてコップ本に書いてあった。
__何か__ を共通のモノにできない場合は、設計を疑った方が良いのかもね。

# <a name="まとめ">まとめ</a>
抽出子は使いこなすと強力な武器になりそうだろ？ 
ぜひ使ってみてね！

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