基础类型匹配
首先我们看下最基础的匹配:
package example
import scala.annotation.switch
object MyExample {
def main(args: Array[String]): Unit = {
val n = 11
val res = n match {
case 1 => n + 1
case 2 | 3 | 4 => n + 2 // 可以匹配多个
case 10 => n * 10
case _ => { // 匹配不上
println("miss match")
n - 1
}
}
println(res)
}
}
代码输出:
miss match
10
Option类型匹配
一般来说,我们不要在scala中使用空值,更推荐使用Option的方式。使用Option必然经常使用match,因此直接在这里介绍。直接给出代码实例:
package example
object MyExample {
def message(n: Int): Option[String] = {
if (n > 0) {
Option("hello foo")
} else {
None
}
}
def getMessage(message: Option[String]): Unit = {
message match {
case Some(msg) => println(s"Get msg: $msg")
case None => println("Get None !!")
}
}
def main(args: Array[String]): Unit = {
val msg1 = message(1)
val msg2 = message(-1)
getMessage(msg1)
getMessage(msg2)
}
}
代码输出:
Get msg: hello foo
Get None !!
case class 匹配
之后,我们看下case class的匹配,先看最基本的一种:
package example
// 声明为sealed, 子类必须在同一个文件中
sealed abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class WeChat(caller: String, message: String) extends Notification
case class VoiceRecording(contentName: String, link: String) extends Notification
case class WrongMsg(content: String) extends Notification
object MyExample {
def getNotification(notification: Notification): Unit = {
notification match {
case Email(sender, title, body) => {
println(s"$sender send you a email, title: $title, body: $body")
}
case WeChat(caller, _) => { // _ 省略内容
println(s"$caller gives you a wechat message")
}
case VoiceRecording(_, link) => { // _ 省略内容
println(s"you have a voice, link is $link")
}
case _ => {
println("wrong type msg")
}
}
}
def main(args: Array[String]): Unit = {
val email = Email("foo", "Hello", "Hello, I am foo")
val weChat = WeChat("foo2", "Hi foo")
val voiceRecording = VoiceRecording("foo voice", "www.foovoice.link")
val wrongMsg = WrongMsg("")
getNotification(email)
getNotification(weChat)
getNotification(voiceRecording)
getNotification(wrongMsg)
}
}
代码输出:
foo send you a email, title: Hello, body: Hello, I am foo
foo2 gives you a wechat message
you have a voice, link is www.foovoice.link
wrong type msg
模式守卫
有些情况下,我们想要让匹配的case class再满足某种条件,才会继续执行后面的代码块,举个例子:
package example
import scala.annotation.switch
// 声明为sealed, 子类必须在同一个文件中
sealed abstract class Animal
case class Cat(name: String, age: Int) extends Animal
case class Dog(name: String, master: String) extends Animal
case class Bird(name: String, canFly: Boolean) extends Animal
object MyExample {
def getAnimal(animal: Animal): Unit = {
animal match {
case Bird(name, canFly) if (canFly) => println(s"Bird $name can fly")
case Dog(name, master) if (master.length > 0) => println(s"Dog $name has master")
case Cat(name, age) => println(s"Cat $name is $age years old")
case _ => {}
}
}
def main(args: Array[String]): Unit = {
val bird = Bird("foo-bird", true)
val dog = Dog("foo-dog", "") // 不会执行
val cat = Cat("foo-cat", 3)
getAnimal(bird)
getAnimal(dog)
getAnimal(cat)
}
}
代码输出:
Bird foo-bird can fly
Cat foo-cat is 3 years old
仅类型匹配
我们可以仅仅匹配类型,然后对匹配上类型的变量执行操作,举个例子:
package example
import scala.annotation.switch
// 声明为sealed, 子类必须在同一个文件中
sealed abstract class Device
case class Phone(name: String) extends Device
case class PC(name: String) extends Device
case class Watch(name: String) extends Device
object MyExample {
def getDevice(device: Device): Unit = {
device match {
case phone: Phone => println(s"Phone: ${phone.toString}")
case pc: PC => println(s"PC: ${pc.toString}")
case watch: Watch => println(s"Watch: ${watch.toString}")
case _ => {}
}
}
def main(args: Array[String]): Unit = {
val phone = Phone("iPhone")
val pc = PC("MacBookPro")
val watch = Watch("iWatch")
getDevice(phone)
getDevice(pc)
getDevice(watch)
}
}
代码输出:
Phone: Phone(iPhone)
PC: PC(MacBookPro)
Watch: Watch(iWatch)