Scala - Extractores

Un extractor en Scala es un objeto que tiene un método llamado unapplycomo uno de sus miembros. El propósito de ese método de no aplicar es hacer coincidir un valor y desarmarlo. A menudo, el objeto extractor también define un método dualapply para construir valores, pero esto no es obligatorio.

Ejemplo

Tomemos un ejemplo de objeto define tanto apply y unapplymétodos. El método de aplicación tiene el mismo significado que siempre: convierte a Test en un objeto que se puede aplicar a los argumentos entre paréntesis de la misma manera que se aplica un método. Entonces puede escribir Test ("Zara", "gmail.com") para construir la cadena "[email protected]".

los unapply El método es lo que convierte la clase Test en un extractor e invierte el proceso de construcción de apply. Donde aplicar toma dos cadenas y forma una cadena de dirección de correo electrónico a partir de ellas, una aplicación toma una dirección de correo electrónico y devuelve potencialmente dos cadenas:user y el domain de la dirección.

los unapplytambién debe manejar el caso donde la cadena dada no es una dirección de correo electrónico. Es por eso que unapply devuelve un tipo Option sobre pares de cadenas. Su resultado esSome (user, domain)si la cadena str es una dirección de correo electrónico con el usuario y las partes del dominio dadas, o Ninguno, si str no es una dirección de correo electrónico. A continuación se muestran algunos ejemplos.

Sintaxis

unapply("[email protected]") equals Some("Zara", "gmail.com")
unapply("Zara Ali") equals None

El siguiente programa de ejemplo muestra un objeto extractor para direcciones de correo electrónico.

Ejemplo

object Demo {
   def main(args: Array[String]) {
      println ("Apply method : " + apply("Zara", "gmail.com"));
      println ("Unapply method : " + unapply("[email protected]"));
      println ("Unapply method : " + unapply("Zara Ali"));
   }
   
   // The injection method (optional)
   def apply(user: String, domain: String) = {
      user +"@"+ domain
   }

   // The extraction method (mandatory)
   def unapply(str: String): Option[(String, String)] = {
      val parts = str split "@"
      
      if (parts.length == 2){
         Some(parts(0), parts(1)) 
      } else {
         None
      }
   }
}

Guarde el programa anterior en Demo.scala. Los siguientes comandos se utilizan para compilar y ejecutar este programa.

Mando

\>scalac Demo.scala
\>scala Demo

Salida

Apply method : [email protected]
Unapply method : Some((Zara,gmail.com))
Unapply method : None

Coincidencia de patrones con extractores

Cuando una instancia de una clase va seguida de paréntesis con una lista de cero o más parámetros, el compilador invoca el applymétodo en esa instancia. Podemos definir aplicar tanto en objetos como en clases.

Como se mencionó anteriormente, el propósito de la unapplyEl método consiste en extraer un valor específico que estamos buscando. Hace la operación contrariaapplyhace. Al comparar un objeto extractor utilizando elmatch declaración el unapply El método se ejecutará automáticamente.

Pruebe el siguiente programa de ejemplo.

Ejemplo

object Demo {
   def main(args: Array[String]) {
      val x = Demo(5)
      println(x)

      x match {
         case Demo(num) => println(x+" is bigger two times than "+num)
         
         //unapply is invoked
         case _ => println("i cannot calculate")
      }
   }
   def apply(x: Int) = x*2
   def unapply(z: Int): Option[Int] = if (z%2==0) Some(z/2) else None
}

Guarde el programa anterior en Demo.scala. Los siguientes comandos se utilizan para compilar y ejecutar este programa.

Mando

\>scalac Demo.scala
\>scala Demo

Salida

10
10 is bigger two times than 5