From 101daabcd077bb510ad2a33e86b60063c965dc98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9A=D0=BE=D1=80=D1=81?= =?UTF-8?q?=D0=B0=D0=BA=D0=BE=D0=B2?= Date: Tue, 27 Jun 2023 09:12:22 +0300 Subject: [PATCH] Update extractor-objects.md in russian --- _ru/tour/extractor-objects.md | 62 ++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/_ru/tour/extractor-objects.md b/_ru/tour/extractor-objects.md index 5be38a2c2f..f93981cd6c 100644 --- a/_ru/tour/extractor-objects.md +++ b/_ru/tour/extractor-objects.md @@ -10,6 +10,10 @@ previous-page: regular-expression-patterns Объект Экстрактор (объект распаковщик или extractor object) - это объект с методом `unapply`. В то время как метод `apply` обычно действует как конструктор, который принимает аргументы и создает объект, метод `unapply` действует обратным образом, он принимает объект и пытается извлечь и вернуть аргументы из которых он (возможно) был создан. Чаще всего этот метод используется в функциях сопоставления с примером и в частично определенных функциях. +{% tabs extractor-objects_definition class=tabs-scala-version %} + +{% tab 'Scala 2' for=extractor-objects_definition %} + ```scala mdoc import scala.util.Random @@ -29,32 +33,82 @@ customer1ID match { case _ => println("Could not extract a CustomerID") } ``` + +{% endtab %} + +{% tab 'Scala 3' for=extractor-objects_definition %} + +```scala +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") +``` + +{% endtab %} + +{% endtabs %} + Метод `apply` создает `CustomerID` из строки `name`. `unapply` делает обратное, чтобы вернуть `name` обратно. Когда мы вызываем `CustomerID("Sukyoung")`, это сокращенный синтаксис вызова `CustomerID.apply("Sukyoung")`. Когда мы вызываем `case CustomerID(name) => println(name)`, мы на самом деле вызываем метод `unapply`. При объявлении нового значения можно использовать пример, в котором значение для инициализации переменной получается через извлечение, используя метод `unapply`. +{% tabs extractor-objects_use-case-1 %} + +{% tab 'Scala 2 и 3' for=extractor-objects_use-case-1 %} + ```scala mdoc val customer2ID = CustomerID("Nico") val CustomerID(name) = customer2ID println(name) // выведет Nico ``` +{% endtab %} + +{% endtabs %} + Что эквивалентно `val name = CustomerID.unapply(customer2ID).get`. +{% tabs extractor-objects_use-case-2 %} + +{% tab 'Scala 2 и 3' for=extractor-objects_use-case-2 %} + ```scala mdoc val CustomerID(name2) = "--asdfasdfasdf" ``` +{% endtab %} + +{% endtabs %} + Если совпадений нет, то бросается `scala.MatchError`: +{% tabs extractor-objects_use-case-3 %} + +{% tab 'Scala 2 и 3' for=extractor-objects_use-case-3 %} + ```scala mdoc:crash val CustomerID(name3) = "-asdfasdfasdf" ``` +{% endtab %} + +{% endtabs %} + Возвращаемый тип `unapply` выбирается следующим образом: -* Если это всего лишь тест, возвращается `Boolean`. Например `case even()`. -* Если в результате найдено одно значение типа `T`, то возвращается `Option[T]`. -* Если вы хотите получить несколько значений `T1,..., Tn`, то ответ необходимо группировать в дополнительный кортеж `Option[(T1,..., Tn)]`. +- Если это всего лишь тест, возвращается `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 @ _*) =>`. +Иногда количество извлекаемых значений не является фиксированным. Если в зависимости от входа мы хотим вернуть произвольное количество значений, то для этого случая мы можем определить экстрактор методом `unapplySeq`, который возвращает `Option[Seq[T]]`. Характерным примером такого подхода является разложение `List` с помощью `case List(x, y, z) =>` и разложение `String` с помощью регулярного выражения `Regex`, такого как `case r(name, remainingFields @ _*) =>`.