Tour of Scala

抽出子オブジェクト

Language

抽出子オブジェクトはunapplyメソッドを持つオブジェクトです。 applyメソッドが引数を取り、オブジェクトを作るコンストラクタであるように、unapplyは1つのオブジェクトを受け取り、引数を返そうとします。 これはパターンマッチングと部分関数で最も頻繁に使われます。

import scala.util.Random

object CustomerID {

  def apply(name: String) = s"$name--${Random.nextLong}"

  def unapply(customerID: String): Option[String] = {
    val stringArray: Array[String] = customerID.split("--")
    if (stringArray.tail.nonEmpty) Some(stringArray.head) else None
  }
}

val customer1ID = CustomerID("Sukyoung")  // Sukyoung--23098234908
customer1ID match {
  case CustomerID(name) => println(name)  // prints Sukyoung
  case _ => println("Could not extract a CustomerID")
}

applyメソッドはnameからCustomerID文字列を作ります。unapplyは逆にnameを返します。 CustomerID("Sukyoung")は、CustomerID.apply("Sukyoung")を短く書く構文です。 case CustomerID(name) => println(name)では、unapplyメソッドを呼んでいます。

値を定義する文で、パターン中に新しい変数を使うことができるので、抽出子は変数を初期化するのに使えます。この場合unapplyメソッドが初期値を与えます。

val customer2ID = CustomerID("Nico")
val CustomerID(name) = customer2ID
println(name)  // prints Nico

これは val name = CustomerID.unapply(customer2ID).get.と同じです。

val CustomerID(name2) = "--asdfasdfasdf"

もし一致しない場合scala.MatchErrorが投げられます。

val CustomerID(name3) = "-asdfasdfasdf"

unapplyの戻り値型は以下のように選ばれなければなりません。

  • ただのテストであれば、Booleanを返します。例えばcase even()
  • T型のサブバリュー1つを返すのであれば、Option[T]を返します。
  • いくつかのサブバリューT1,...,Tnを返したいのであれば、オプショナルタプルOption[(T1,...,Tn)]でグループ化します。

時々、抽出する値の数が確定せず、入力に応じて任意の数の値を返したいことがあります。 この場合は、Option[Seq[T]]を返すunapplySeqメソッドを持つ抽出子を定義することができます。 これらのパターンと同様の例として以下のものがあります。 case List(x, y, z) =>を使ってListを分解する例やcase r(name, remainingFields @ _*) =>.のように正規表現Regexを使ってStringを分解する例です。

Contributors to this page: