- match表达式是一个更好的switch,不会有意外调入下一个分支的问题。其他语言需要使用break来避免。
- 如果没有模式能够匹配,会抛出MatchError,可以用case _模式来避免。
- 模式可以包含一个随意定义的条件,叫做守卫。
- 你可以对表达式的类型进行匹配。优先选择模式匹配而不是isInstanceOf。
- 你可以匹配数组,元组,样例类的模式,然后将匹配到的不同部分帮顶到变量。
- 在for表达式中,不能匹配的情况会被安静的跳过。
- 样例类是编译器会为之自动产出模式匹配所需要的方法的类。
- 用Option来存放对于可能存在也可能不存在的值,这比null更安全。
更好的switch
var sign = ch match {
case '+' => 1
case '-' => -1
case _ if Character.isDigit(ch) => digit = Character.digit(ch)
//添加守卫,守卫可以是任何Boolean条件
case _ => 0
}
模式中的变量
如果case后面跟着一个变量名,那么匹配的表达式会被赋值给那个变量。你当然可以在守卫中使用变量:
str(i) match {
case '+' => sign = 1
case '-' => sign = -1
case ch if Character.isDigit(ch) => digit = Character.digit(ch)}
scala可以识别你匹配的是变量还是常量:
import scala.math._
x match{
case Pi => ...
//scala不会把Pi当成一个变量。
...
}
类型匹配
obj match {
case x : Int => x
//匹配的表达式会被绑定到变量x
case s : String => Integer.parseInt(s)
case _ : BigInt => Int.MaxValue
case _ : => 0
}
匹配数组,列表和元组
利用模式匹配可以很轻松的访问复杂结构的各组成部分,这种操作被称作“析构”。
arr match{
case Array(0) => "0"
//匹配包含0的数组
case Array(x,y) => x + " " + y
//匹配两个元素的数组,并把数组元素分别赋值给x,y
case Array(0,_*) => "0..."
//匹配以0开始的数组
case _ => "something else"}
lst match {
case 0 :: Nil => "0"
case x :: y :: Nil => x + " " + y
case 0 :: tail => "0..."
case _ => "something else"}
pair match {
case (0,_) => "0..."
case (y, 0) => y + " 0"
case _ => "neither is 0"}
提取器
上面的模式匹配数组,列表和元组,这些操作的背后是提取器机制----带有从对象中提取值的unapply,unapplySeq方法的对象。unapply用于提取固定数量的对象,unapplySeq提取的是一个序列。
arr match {
case Array(0,x) => ...
...
}
Array伴生对象是一个提取器,它定义了unapplySeq方法,Array.unapplySeq(arr)产出一个序列的值,第一个值与0进行比较,第二个值赋值给x。
val pattern = "([0-9]+) ([a-z]+)".r
"99 bottles" match{
case pattern(num,item) => ...
//将num设为99,item设为"bottles"}
变量声明中的模式
val (x , y ) = (1,2)
val Array(first , second , _*) = arr
for表达式中的模式
for((k,v) <- System.getProperties())
println(k + "->"+v)
for((k,"") <- System.getProperties())
println(k)
//失败的匹配会被安静的忽略,这条语句只会打印出值为空白的键
样例类
样例类是一种特殊的类,它们经过优化以被用于模式匹配。 当你声明样例类时,下面几件事情会自动发生:
- 构造器中的每个参数都成为val
- 在伴生对象中提供apply方法,让你不用new关键字就能构造出相应的对象。
- 提供unapply方法让模式匹配可以工作。
object CaseClassDemo extends App{
def m(p : Person){
p match {
case Teacher(_) => println("This is a teacher")
case Teacher("Peter") => println("This is teacher Peter")
case Student(_) => println("This is a student")
case _ => println("This is unknown")
}
}
m(Student("A"))
//"This is a student"
m(Teacher("A"))
//"This is a teacher"
m(Teacher("Peter"))
//"This is a teacher Peter"
}
abstract class Person
case class Teacher(name : String) extends Person
case class Student(name : String) extends Person
模拟枚举
样例类可以让你在Scala中模拟出枚举类型
sealed abstract class TrafficLightColor
//将TrafficLightColor声明为sealed(密封类)可以让编译器为我们检查match语句是否列出了所有的情况。
case object Red extends TrafficLightColor
case object Yellow extends TrafficLightColor
case object Green extends TrafficLightColor
color match {
case Red => "stop"
case Yellow => "hurry up"
case Green => "go"
}
Option类型
标准库中的Option类型用样例类来表示那些可能存在,也可能不存在的值。 Option支持泛型,Some("Fred")的类型为Option[String]
scores.get("Alice") match {
case Some(score) => println(score)
case None => println("No score")}
scores.getOrElse("Alice","No score")
Comments !