Сопоставление с образцом в Scala
Scala предоставляет мощный механизм сопоставления с образцом, и он также широко используется.
Сопоставление с образцом содержит ряд альтернатив, каждая из которых начинается с ключевого словаcase. Каждая альтернатива содержит образец и одно или несколько выражений. Символ стрелки=>разделяет образец и выражения.
Ниже приведён простой пример сопоставления с образцом для целочисленного значения:
Пример
def main(args: Array[String]) {
println(matchTest(3))
}
def matchTest(x: Int): String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many"
}
}
Выполнение приведенного выше кода дает следующий вывод:
$ scalac Test.scala $ scala Test many
match соответствует switch в Java, но пишется после выражения-селектора. То есть:selector match { alternatives }.
Выражение match вычисляется путём проверки каждого шаблона в порядке, записанном в коде. Как только находится совпадающий case, остальные case больше не проверяются.
Далее рассмотрим пример сопоставления с образцом для различных типов данных:
Пример
def main(args: Array[String]) {
println(matchTest("two"))
println(matchTest("test"))
println(matchTest(1))
println(matchTest(6))
}
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y: Int => "scala.Int"
case _ => "many"
}
}
Выполнение приведенного выше кода дает следующий вывод:
$ scalac Test.scala $ scala Test 2 many one scala.Int
В примере первый case соответствует целочисленному значению 1, второй case соответствует строковому значению two, а третий case соответствует шаблону типа, используемому для определения, является ли переданное значение целым числом. По сравнению с использованием isInstanceOf для определения типа, использование сопоставления с образцом лучше. Четвёртый case представляет вариант полного совпадения по умолчанию, то есть элемент match, когда не найдено других совпадений, аналогично default в switch.
Использование case-классов
Определение класса, использующее ключевое слово case, — это case-класс. Case-классы — это особый вид классов, оптимизированный для сопоставления с образцом.
Ниже приведён простой пример case-класса:
Пример
def main(args: Array[String]) {
val alice = new Person("Алиса", 25)
val bob = new Person("Боб", 32)
val charlie = new Person("Чарли", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Алиса", 25) => println("Привет, Алиса!")
case Person("Боб", 32) => println("Привет, Боб!")
case Person(name, age) =>
println("Возраст: " + age + " лет, имя: " + name + "?")
}
}
}
// Case-класс
case class Person(name: String, age: Int)
}
Выполнение приведенного выше кода дает следующий вывод:
$ scalac Test.scala $ scala Test Hi Alice! Hi Bob! Age: 32 year, name: Charlie?
Когда объявляется case class, автоматически происходит следующее:
- Каждый параметр конструктора становится val, если только он явно не объявлен как var, но это не рекомендуется;
- В сопутствующем объекте предоставляется метод apply, поэтому объекты можно создавать без использования ключевого слова new;
- Предоставляется метод unapply, чтобы работало сопоставление с образцом;
- Методы toString, equals, hashCode и copy генерируются, если эти методы не определены явно.