Scala中,extractors(提取器)是一个object,功能和case class类似,用来匹配特定的模式。
Extractor中,都会包含一个unapply方法,用于匹配特定值并将其进行拆分成多个属性;同时可以包含apply方法(可选),用于从多个属性构造出特定的值。比如:
scala> object Email{
| def apply(user:String,domain:String) = user + "@" + domain
| def unapply(mail:String) : Option[(String,String)] = {
| val arr = mail.split("@")
| if(arr.length == 2) Some(arr(0),arr(1)) else None
| }
| }
defined object Email
scala> Email("dreamer","host")
res0: String = dreamer@host
scala> val mailAddr = "alice@dreamhost"
mailAddr: String = alice@dreamhost
scala> mailAddr match {
| case Email(user,domain) => println(user + "'s email address")
| case _ => println("Not a valid email address")
| }
alice's email address
Email中,由于unapply方法的参数不一定都符合邮件格式,所以返回值类型为Option,匹配的时候返回Some,不匹配的时候返回None。Scala中,object名后直接跟小括号会调用object的apply方法,不过在match表达式中,调用的是extractor的unapply方法。
对于提取固定属性参数,上面的定义可以应付,不过,如果要处理变长属性参数,上面的定义方式就无能为力了。为了让extractor就能处理变长属性参数,需要将unapply方法替换为unapplySeq,同时将返回值类型改为Option[Seq[T]]即可。示例如下:
scala> object PathResolver {
| def apply(dirs:String*) = dirs.mkString("/")
| def unapplySeq(dir:String):Option[Seq[String]] = Some(dir.split("/"))
| }
defined object PathResolver
scala> PathResolver("","usr","local","lib")
res7: String = /usr/local/lib
scala> def isInUserDir(dir:String) = {
| dir match {
| case PathResolver("","usr",_*) => true
| case _ => false
| }
| }
isInUserDir: (dir: String)Boolean
scala> isInUserDir("/usr/local")
res8: Boolean = true
scala> isInUserDir("/root")
res9: Boolean = false
参考自:Programming Scala 2nd Edition
阅读(1159) | 评论(0) | 转发(0) |