Этот блог проведет вас через базовое понимание экстракторов в 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 следует выбирать, помня о следующих вещах:

  1. Если он возвращает одно подзначение типа T, верните Option[T].
  2. Если это просто тест, верните логическое значение.
  3. Если вы хотите вернуть несколько подзначений 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 г.