match 模式匹配
基本介绍
- Scala 中的模式匹配类似于 Java 中的 switch 语法,但是更加强大
- 模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需要匹配时,会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句
val oper = '-'
val n1 = 20
val n2 = 10
var res = 0
//说明
//1. match (类似 java switch) 和case 是关键字
//2. 如果匹配成功, 则 执行 => 后面的代码块.
//3. 匹配的顺序是从上到下,匹配到一个就执行对应的 代码
//4. => 后面的代码块 不要写 break ,会自动的退出 match
//5. 如果一个都没有匹配到,则执行 case _ 后面的代码块
oper match {
case '+' => res = n1 + n2
case '-' => res = n1 - n2
case '*' => res = n1 * n2
case '/' => res = n1 / n2
case _ => println("oper error")
}
println("res=" + res)
守卫
- 如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫
// 说明..
// 如果 case 后有 条件守卫即 if ,那么这时的 _ 不是表示默认匹配
// 表示忽略 传入 的 ch
case _ if ch.toString.equals("3") => digit = 3
case _ if (ch > 1110 || ch < 120) => println("ch > 10")
模式中的变量
- 如果在 case 关键字后跟变量名,那么 match 前表达式的值会赋给那个变量
ch match {
case '+' => println("ok~")
// 下面 case mychar 含义是 mychar = ch
case mychar => println("ok~" + mychar)
case _ => println ("ok~~")
}
类型匹配
- 可以匹配对象的任意类型,这样做避免了使用 isInstanceOf 和 asInstanceOf 方法
val result = obj match {
case a: Int => a
case b: Map[String, Int] => "对象是一个字符串-数字的 Map 集合"
case c: Map[Int, String] => "对象是一个数字-字符串的 Map 集合"
}
类型匹配注意事项
- Map[String, Int] 和 Map[Int, String]是两种不同的类型,其它类推
- 在进行类型匹配时,编译器会预先检测是否有可能的匹配,如果没有则报错
val result = obj match {
case i : Int => i
}
//case i : Int => i 表示 将 i = obj (其它类推),然后再判断类型
- 如果 case _ 出现在 match 中间,则表示隐藏变量名,即不使用,而不是表示默认匹配
- unapply 方法是对象提取器
for循环模式匹配
for ((k, v) <- map if v >= 1) {
println(k + " ---> " + v)
}
样例(模板)类
-
- 样例类仍然是类
-
- 样例类用 case 关键字进行声明。
-
- 样例类是为模式匹配而优化的类
-
- 构造器中的每一个参数都成为 val——除非它被显式地声明为 var(不建议这样做)
-
- 在样例类对应的伴生对象中提供 apply 方法让你不用 new 关键字就能构造出相应的对象
-
- 提供 unapply 方法让模式匹配可以工作
-
- 将自动生成 toString、equals、hashCode 和 copy 方法(有点类似模板类,直接生成)
-
- 除上述外,样例类和其他类完全一样。你可以添加方法和字段,扩展它们
abstract class Amount
case class Dollar(value: Double) extends Amount //样例类
case class Currency(value: Double, unit: String) extends Amount //样例类
case object NoAmount extends Amount //样例类
case 语句的中置(缀)表达式
List(1, 3, 5, 9) match { //测试
//1.两个元素间::叫中置表达式,至少 first,second 两个匹配才行.可以多 但最后一个匹配剩余的
//2.first 匹配第一个 second 匹配第二个,third匹配第三个 rest 匹配剩余部分(5,9)
case first :: second :: third :: rest => println(first + " " + second + " " + " " + third + rest.length + " " + rest) //
case _ => println("匹配不到...")
}
//结果: 1 3 5 1 List(9)
密封类
- 如果让case类的所有子类都必须声明在该类的相通源文件中定义 可以将样例类的通用超类声明为
sealed
,这个超类称之为密封类
- 密封类不能再其他文件中定义子类