在Scala中Extractor为定义了unapply方法的对象。unapply的作用是匹配一个值,然后从中提取所需的部分。通常unapply和apply一起定义,但这不是必须的。例如,前面定义上篇文章中所需的Email对象。
object EMail { 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 } }
Email对象定义了apply和unapply方法,apply方法没有什么特别之处,而unapply方法则把EMail对象变成了一个Extractor。在某种程度上来说,unapply和apply的作用相反,apply方法把两个字符串参数变成一个Email地址,而unapply方法反向变换,把一个字符串分解成两个部分:用户名和域名。unapply方法必须处理不能把一个字符串分解成两部分的情况,这也是为什么这里unapply方法返回Option类型的原因。
简单的测试如下:
scala> EMail.unapply("james@guidebee.com") res1: Option[(String, String)] = Some((james,guidebee.com)) scala> EMail.unapply("James Shen") res2: Option[(String, String)] = None
现在,模式匹配碰到一个模式引用到一个Exactor对象时,会调用该对象的unapply方法,比如
selectorString match { case EMail(user,domain) => ...
会调用
EMail.unapply(selectorString)
例如:
"james.shen@guidebee.com" match{ case EMail(user,domain) => println (user +" AT " + domain) case _ => } james.shen AT guidebee.com