有趣的Scala模式匹配

Posted 鸿的学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有趣的Scala模式匹配相关的知识,希望对你有一定的参考价值。

Scala提供了一种类比switch/case更为强大的选择匹配模式,写作

选择语句 match {可选分支}

它被称为模式匹配,模式匹配包含了一系列以case关键字开头的分支,每一个分支包含一个模式或者是多个表达式。模式有很多种,例如常量模式('*',1),变量模式(可以匹配任何值),通配模式(又见面了,'_'符号),构造方法模式(类似于样例类的初始化)等等。
用一个例子简单说明就是:

scala> def matchTest(expr:Int) = expr match {
    |     case 1 => println(1)
    |     case 2 => println(2)
    |     case _ => println(3)
    |   }
matchTest: (expr: Int)Unit

scala> matchTest(1)
1

scala> matchTest(2)
2

scala> matchTest(4)
3

match表达式会逐个尝试case里的模式直到匹配为止,如果没有匹配上就会抛出异常MatchError,所以一定要确保case都被覆盖。上例所展示的就是常量模式的常量1,2去匹配,还使用了_通配符匹配任何对象(建议放在最后面,因为Scala的模式匹配是按顺序的)。类似于通配符,为了使用传入的变量,还可以指定变量(当以小写字母开头时,会被认为时变量,然后会被认为是常量),使用变量模式。

scala>  def matchTest(expr:Int) = expr match {
    |     case 0 => println(0)
    |     case some => println(some)
    |   }
matchTest: (expr: Int)Unit

scala> matchTest(0)
0

scala> matchTest(3)
3

当然,除了上述的模式,还可以选择构造方法匹配。例如:

scala> case class Test2(a:String)
defined class Test2

scala> case class Test1(name:String, mt:Test2)
defined class Test1

scala> def matchTest(expr:Test1):Test2 = expr match {
    |     case  Test1("a",e)=> e
    |     case _ => Test2("ab")
    |   }
matchTest: (expr: Test1)Test2

scala> val a = Test2("cd")
a: Test2 = Test2(cd)

scala> val b = Test1("ab",a)
b: Test1 = Test1(ab,Test2(cd))

scala> matchTest(b)
res0: Test2 = Test2(ab)

scala> val b = Test1("a",a)
b: Test1 = Test1(a,Test2(cd))

scala> matchTest(b)
res1: Test2 = Test2(cd)

我们创造了两个样例类Test1和Test2,Test1接受Test2作为构造参数,实例化两个样例类后发现,在构造方法匹配中,Scala采用了深度匹配,这说明模式匹配不仅仅会检查类是否相等,还会检查对象的内容是否匹配。由构造方法匹配自然而然就可以引申为序列模式匹配和元组匹配。
序列模式匹配

scala> def matchTest(expr:List[String]):Unit = expr match {
    |     case  List("a",_,_)=> println("right")
    |     case _ => println("wrong")
    |   }
matchTest: (expr: List[String])Unit

scala> matchTest(List("a"))
wrong

scala> matchTest(List("a","b","c"))
right

可以使用_*来省略后面的多个_符号
元组模式

scala>   def matchTest(expr:Any):Unit = expr match {
    |     case  (a,b,c)=> println("found:" +a+b+c)
    |     case _ => println("wrong")
    |   }
matchTest: (expr: Any)Unit

scala> matchTest(("a","b","c"))
found:abc

匹配类型的模式
除了上述的匹配模式选出值,还可以用来做类型检查和测试。这里可以根据传进去的值的类型反馈对应的结果。

scala>   def matchTest(expr:Any) = expr match {
    |     case s:String=> s.length
    |     case i:Int => i
    |   }
matchTest: (expr: Any)Int

scala> matchTest("abc")
res5: Int = 3

scala> matchTest(2)
res6: Int = 2


以上是关于有趣的Scala模式匹配的主要内容,如果未能解决你的问题,请参考以下文章

Scala 基础(十三):Scala 模式匹配

Scala 模式匹配

必会Scala之模式匹配和样例类

Scala模式匹配错误,“错误的简单模式:错误使用_ *(不允许序列模式)”

Scala总结之模式匹配

scala 模式匹配