Этот блог проведет вас через базовое понимание экстракторов в Scala.
extractor
– это объект с методом unapply
. Он принимает объект в качестве входных данных и возвращает аргументы. Пользовательские экстракторы создаются с использованием метода unapply. Метод unapply
называется extractor
, потому что он берет элемент того же набора и извлекает некоторые его части, метод apply
, также называемый внедрением, действует как конструктор, принимает некоторые аргументы и возвращает элемент заданного набора. .
case class
в Scala по умолчанию реализует методы apply
и unapply
.
Case Classes
особенные, потому что Scala автоматически создает для них сопутствующий объект: одноэлементный объект, который содержит не только метод применения для создания новых экземпляров case class
, но и unapply
метод, который должен быть реализован объектом, чтобы он был extractor
.
case class Blog (name: String, length: Int)
Метод «apply
» вызывается при создании экземпляра case class
:
val blog = Blog("extractor", 140)
val name = Blog.unapply(blog).get
такое же, как:
val Blog(name,length) = blog
Lдавайте разберемся с экстракторами на примерах:
Тип возвращаемого значения unapply
следует выбирать, помня о следующих вещах:
- Если он возвращает одно подзначение типа
T
, вернитеOption[T].
- Если это просто тест, верните логическое значение.
- Если вы хотите вернуть несколько подзначений
T1,...,Tn
, сгруппируйте их в необязательный кортежOption[(T1,...,Tn)]
.
Давайте обсудим все три пункта один за другим:
Когда значение не совпадает в случае, выдается ошибка совпадения.
ОДНА ПОДЗНАЧЕНИЕ
object Math { def apply(number: Int): Int = number * number def unapply(number: Int): Option[Int] = { if (number % 2 == 0) Some(number / 2) else None } } val obj = Math (2) val objectOne = Math (1) //match error is thrown obj match { case Math (number) => // invoke Math.unapply println (number) // prints 2 }
val object = Math(2)
расширяется до val object = Math.apply(2)
НЕСКОЛЬКО ПОДЗНАЧЕНИЙ
object DemoAddr { def unapply(addr: String): Option[(String, String, String, String)]= { val tokens = addr split "\\." if (tokens.length == 4) Some(tokens(0), tokens(1), tokens(2), tokens(3)) else None } } "127.0.0.1" match { case DemoAddr (addr, _, _, _) => println ("matched!!" + addr) } // prints matched!!127
БУЛЕВОЕ ЗНАЧЕНИЕ
def unapply (addr: String): Boolean = { val tokens = addr split "\\." if (tokens.length == 4 && isValid (tokens) ) true else false } "127.0.0.1" match { case DemoAddr () => println ("Valid") // prints Valid case _ => println ("Invalid") }
Если у вас есть переменное количество значений аргументов, scala предоставляет метод извлечения unapplySeq
.
object DemoAddresses { def unapplySeq(ips: String): Option[Seq[String]] = { Some(ips split ",") } } "192.168.0.1,192.168.0.2,192.168.0.3,192.168.0.4" match { case DemoAddrress (DemoAddr (a, _, _, _), DemoAddr (b, _, _, _), _*) => println (a + " " + b) case _ => println ("Invalid IP addresses") } // prints 192 192
Давайте разберемся, в каком порядке вызываются экстракторы:
object EMailValidator { def apply(user: String, domain: String) = user + "@" + domain def unapply(str: String): Option[(String, String)] = { val parts = str split "@" if (parts.length == 2) Some(parts(0), parts(1)) else None } } object Twice { def apply(str: String): String = str + str // concatenates string with itself def unapply(str: String): Option[String] = { val length = str.length / 2 val half = str.substring(0, length) if (half == str.substring(length)) Some(half) else None } object UpperCase { def unapply(str: String): Boolean = str.toUpperCase == str // returns true if string is in uppercase else false } def userTwiceUpper(s: String) = s match { case EMailValidator(Twice(x@UpperCase()), domain) => "match:" + x + "in domain" + domain case => "no match" }
EMailValidator(Twice(x @ UpperCase()), domain) порядок вызова слева направо.
EmailValidator делит «[email protected]» на «DIDI» и «hotmail.com» (пользователь и домен). Дважды будет вызван пользователь, и метод unapply преобразует его в «DI». Верхний регистр будет вызываться для DI, и будет возвращено значение true. Результат будет:
match: DI in domain hotmail.com
Извлекатели не раскрывают конкретное представление данных. Они включают шаблоны без какой-либо связи с типом данных для выбранного объекта.
Спасибо за чтение!
Первоначально опубликовано на сайте blog.knoldus.com 9 июля 2018 г.