Scala实践10
1、模式匹配
模式匹配是一种根据模式检查值的机制。它是switch(Java中语句)的更强大版本,它同样可以用来代替一系列if / else语句。
- 句法
匹配表达式具有值,match关键字和至少一个case子句。
import scala.util.Random
val x: Int = Random.nextInt(10)
x match {
case 0 => "zero"
case 1 => "one"
case 2 => "two"
case _ => "other"
}
val x上面是0和10之间的随机整数,x成为的左操作数match运算符和右边是与4箱子的表达式。最后一种情况(_)是任何其他可能Int值的“全部捕获”情况。案件也被称为替代品。
- 匹配案例类
案例类对模式匹配特别有用。
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
Notification是具有与壳体的类实现的三个具体的通知类型的抽象超类Email,SMS和VoiceRecording。现在我们可以对这些案例类进行模式匹配:
def showNotification(notification: Notification): String = {
notification match {
case Email(sender, title, _) =>
s"You got an email from $sender 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"
}
}
val someSms = SMS("12345", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
println(showNotification(someSmps))
println(showNotification(someVoiceRecording))
该函数showNotification作为参数的抽象类型Notification和类型相匹配Notification(即,它计算出它是否是一个Email,SMS或VoiceRecording)。在case Email(sender, title, _)字段中sender并且title在返回值中使用但是body忽略该字段_。
- 模式守护
模式保护只是布尔表达式,用于使案例更具体。只需if <boolean expression>在模式后添加。
def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
notification match {
case Email(sender, _, _) if importantPeopleInfo.contains(sender) =>
"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)
}
}
val importantPeopleInfo = Seq("867-5309", "jenny@gmail.com")
val someSms = SMS("867-5309", "Are you there?")
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
val importantEmail = Email("jenny@gmail.com", "Drinks tonight?", "I'm free after 5!")
val importantSms = SMS("867-5309", "I'm here! Where are you?")
println(showImportantNotification(someSms, importantPeopleInfo))
println(showImportantNotification(someVoiceRecording, importantPeopleInfo))
println(showImportantNotification(importantEmail, importantPeopleInfo))
println(showImportantNotification(importantSms, importantPeopleInfo))
在图中case Email(sender, _, _) if importantPeopleInfo.contains(sender),只有sender在重要人物列表中才匹配模式。
- 仅在类型上匹配
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
}
def goIdle具有不同的行为取决于类型Device。当案例需要在模式上调用方法时,这很有用。它是使用类型的情况下标识(第一个字母的公约p和c在这种情况下)。
- 密封课程
可以标记特征和类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"
}
2、案例类
- 定义案例类
最小的案例类需要关键字case class,标识符和参数列表(可能为空):
case class Book(isbn: String)
val frankenstein = Book("912-0111182114")
注意:实例化Book案例时没有new关键字。这是因为case类apply默认有一个方法来处理对象构造。
使用参数创建案例类时,参数是公共val的。
case class Message(sender: String, recipient: String, body: String)
val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?")
println(message1.sender) //合法的
message1.sender = "travis@washington.us" // 不合法的
不能重新分配,message1.sender因为它是一个val(即不可变的)。

浙公网安备 33010602011771号