Scala之旅 8 萃取器对象(Extractor Object)

Scala中,模式独立于Case Class来定义,一个名字为unapply的方法用来产生一个萃取器。比如下面的代码定义一个萃取器对象Twice:
object Twice {                              
  def apply(x: Int): Int = x * 2
  def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
}

object TwiceTest extends Application {
  val x = Twice(21)
  x match { case Twice(n) => Console.println(n) } // prints 21
}



为了使代码能够正常工作,有两个语法约定:

1. 模式 case Twice(n)将会调用 Twice.unapply来匹配偶数。unapply的返回值来标识参数匹配与否。示例中z/2继续用来做匹配。

2. apply并不是模式匹配所必需的,它只是用来模拟一个构造器。 val x = Twice(21)等价于val x = Twice.apply(21)。

unapply的返回类为Option[Int],实际上有三种可能:

1. 如果仅仅是测试,返回Boolean,类似于ase even()

2. 返回类型T集和中的一个元素,返回类型是Option[T]

3. 如果想要返回一系列类型T的元素T1,...,Tn,把它们组合为一个元组 Option[(T1,...,Tn)]

有的时候返回的元素个数是固定的,有的时候可能需要返回一个序列。有可以顶一个unapplySeq模式,最后一个元素Tn的类型必须是Seq[S],这样就可以使用case List(x1, ..., xn)模式了。

其实上面的例子,不过参数值是21还是其他数,输出总是自身。为什么喃?因为模拟构造器总是返回一个偶数,输出也是自身了。可以改成如下:

object Twice {                              
  def apply(x: Int): Int = x
  def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None
}

object TwiceTest extends Application {
  val x = Twice(13)
  x match { case Twice(n) => Console.println(n) case _ => Console.println("None")}
}


或者

object Twice {                              
  def apply(x: Int): Int = x * 2
  def unapply(z: Int): Option[Int] = if (z%3 == 0) Some(z/2) else None
}

object TwiceTest extends Application {
  val x = Twice(13)
  x match { case Twice(n) => Console.println(n) case _ => Console.println("None")}
}


这样子更有意思一点。Some的定义如下:

final case class Some[+A](x: A) extends Option[A] {
  def isEmpty = false
  def get = x
}



你可能感兴趣的:(Scala之旅 8 萃取器对象(Extractor Object))