Scala实践10
1、模式匹配
模式匹配是一种根据模式检查值的机制。它是switch(
Java中语句)的更强大版本,它同样可以用来代替一系列if / else语句。
- 句法
匹配表达式具有值,match
关键字和至少一个case
子句。
1 2 3 4 5 6 7 8 9 10 | 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
值的“全部捕获”情况。案件也被称为替代品。
- 匹配案例类
案例类对模式匹配特别有用。
1 2 3 4 5 6 7 | 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
。现在我们可以对这些案例类进行模式匹配:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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>
在模式后添加。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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
在重要人物列表中才匹配模式。
- 仅在类型上匹配
1 2 3 4 5 6 7 8 9 10 11 12 | 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
,这意味着必须在同一文件中声明所有子类型。这确保了所有亚型都是已知的。
1 2 3 4 5 6 7 8 | 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
,标识符和参数列表(可能为空):
1 2 3 | case class Book(isbn: String) val frankenstein = Book( "912-0111182114" ) |
注意:实例化Book
案例时没有new关键字。这是因为case类apply
默认有一个方法来处理对象构造。
使用参数创建案例类时,参数是公共val
的。
1 2 3 4 5 | 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
(即不可变的)。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步