模式匹配
模式匹配是一种根据模式检查值的机制。一个成功的匹配也可以将一个值分解为它的组成部件。它类似于Java中switch语句的强化版本,可以用用于替换一系列if/else语句。
1 语法
匹配表达式需要有一个值,match关键字,以及最少一个case子句。
def matchTest(x:Int):String = x match {
case 1 => "one"
case 2 => "two"
case _ => "many"
}
note:x为match操作符的左操作数,match的右边是具有三个case子句的表达式。
note:case _表示匹配一切。
2 匹配案例类
abstract class Notification
case class Email(sender:String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification
def showNotification(notification: Notification): String = {
notification match {
case Email(email, title, _) => s"You got an email from $email with title: $title"
case SMS(number, message) => s"You got an SMS from $number! Message: $message"
case VoiceRecording(name, link) => s"you received a Voice Recording from $name! Click the link to hear it: $link"
}
}
3 模式守卫
模式守卫是用于将case具体化的布尔表达式,只需要在模式后添加if < boolean expression >
def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
notification match {
case Email(email, _, _) if importantPeopleInfo.contains(email) =>
"You got an email from special someone!"
case SMS(number, _) if importantPeopleInfo.contains(number) =>
"You got an SMS from special someone!"
case other =>
showNotification(other) // nothing special, delegate to our original showNotification function
}
}
4 类型匹配
abstract class Device
case class Phone(model: String) extends Device{
def screenOff = "Turning screen off"
}
case class Computer(model: String) extends Device {
def screenSaverOn = "Turning screen saver on..."
}
def goIdle(device: Device) = device match {
case p: Phone => p.screenOff
case c: Computer => c.screenSaverOn
}
类型匹配通常用于根据模式调用方法的情景,并且使用类型首字母作为case标识符。
5 密封类
可使用sealed标识特质与类,这意味着,被标识类与特质的子类型必须声明在同一个文件中。这确保所有的子类型都是已知的。
sealed abstract class Furniture
case class Couch() extends Furniture
case class Chair() extends Furniture
def findPlaceToSit(piece: Furniture): String = piece match {
case a: Couch => "Lie on the couch"
case b: Chair => "Sit on the chair"
}
密封类对于模式匹配非常有用,因为不需要case _。
6 注意
Scala模式匹配语句对于匹配通过样板类表示的代数类型最有用。通过使用提取器对象的unapply方法,Scala可以独立于样板类定义模式。