Tour of Scala

Объект Экстрактор

Language
Info: JavaScript is currently disabled, code tabs will still work, but preferences will not be remembered.

Объект Экстрактор (объект распаковщик или extractor object) - это объект с методом unapply. В то время как метод apply обычно действует как конструктор, который принимает аргументы и создает объект, метод unapply действует обратным образом, он принимает объект и пытается извлечь и вернуть аргументы из которых он (возможно) был создан. Чаще всего этот метод используется в функциях сопоставления с примером и в частично определенных функциях.

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) // выведет Sukyoung
 case _ => println("Could not extract a CustomerID")
}
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 then Some(stringArray.head) else None
val customer1ID = CustomerID("Sukyoung") // Sukyoung--23098234908
customer1ID match
 case CustomerID(name) => println(name) // выведет Sukyoung
 case _ => println("Could not extract a CustomerID")

Метод apply создает CustomerID из строки name. unapply делает обратное, чтобы вернуть name обратно. Когда мы вызываем CustomerID("Sukyoung"), это сокращенный синтаксис вызова CustomerID.apply("Sukyoung"). Когда мы вызываем case CustomerID(name) => println(name), мы на самом деле вызываем метод unapply.

При объявлении нового значения можно использовать пример, в котором значение для инициализации переменной получается через извлечение, используя метод unapply.

val customer2ID = CustomerID("Nico")
val CustomerID(name) = customer2ID
println(name) // выведет Nico

Что эквивалентно val name = CustomerID.unapply(customer2ID).get.

val CustomerID(name2) = "--asdfasdfasdf"

Если совпадений нет, то бросается scala.MatchError:

val CustomerID(name3) = "-asdfasdfasdf"

Возвращаемый тип unapply выбирается следующим образом:

  • Если это всего лишь тест, возвращается Boolean. Например case even().
  • Если в результате найдено одно значение типа T, то возвращается Option[T].
  • Если вы хотите получить несколько значений T1,..., Tn, то ответ необходимо группировать в дополнительный кортеж Option[(T1,..., Tn)].

Иногда количество извлекаемых значений не является фиксированным. Если в зависимости от входа мы хотим вернуть произвольное количество значений, то для этого случая мы можем определить экстрактор методом unapplySeq, который возвращает Option[Seq[T]]. Характерным примером такого подхода является разложение List с помощью case List(x, y, z) => и разложение String с помощью регулярного выражения Regex, такого как case r(name, remainingFields @ _*) =>.

Contributors to this page:

Contents

AltStyle によって変換されたページ (->オリジナル) /