Scala 提取器

  • 提取器

    Scala中的提取器是一个对象,该对象具有称为unapply的方法作为其成员之一。该方法的目的是匹配值并将其拆开。通常,提取器对象还定义了构建值的对偶方法apply,但这不是必需的。
    例如:
    让我们以一个对象定义为例,同时应用applyunapply方法。apply方法的含义一如既往:将Test变成一个对象,该对象可以以与apply方法相同的方式应用于括号中的参数。因此,您可以编写Test("Zara","gmail.com")来构造字符串“Zara@gmail.com”。
    unapply方法将Test类转换为提取器,并反转apply的构造过程。apply接受两个字符串并从中形成一个电子邮件地址字符串,unapply接受一个电子邮件地址并可能返回两个字符串:用户和地址的域。unapply还必须处理给定字符串不是电子邮件地址的情况。这就是为什么unapply在对字符串上返回选项类型。如果字符串str是具有给定用户和域部分的电子邮件地址,则结果为Some (user, domain),如果str不是电子邮件地址,则结果为None。下面是一些例子。
    
    unapply("Zara@gmail.com") equals Some("Zara", "gmail.com")
    unapply("Zara Ali") equals None
    
    以下示例程序显示了电子邮件地址的提取器对象。
    
    object Demo {
       def main(args: Array[String]) = {
          println ("Apply method : " + apply("Zara", "gmail.com"));
          println ("Unapply method : " + unapply("Zara@gmail.com"));
          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
          }
       }
    }
    
    尝试一下
    输出::
    
    Apply method : Zara@gmail.com
    Unapply method : Some((Zara,gmail.com))
    Unapply method : None
    
  • 用提取器进行模式匹配

    当类的实例后跟带有零个或多个参数的列表的括号时,编译器将在该实例上调用apply方法。我们可以在对象和类中定义应用。如上所述,unapply方法的目的是提取我们正在寻找的特定值。它相反的操作应用一样。使用match语句比较提取器对象时,将自动执行unapply方法。请尝试以下示例程序。
    
    object Demo {
       def main(args: Array[String]) ={
          val x = Demo(5)
          println(x)
    
          x match {
             case Demo(num) => println(s"$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
    }
    
    编译&运行
    
    \>scalac Demo.scala
    \>scala Demo
    
    输出:
    
    10
    10 is bigger two times than 5