pattern matching能够说是scala中十分强大的一个语言特性,固然这不是scala独有的,但这不妨碍它成为scala的语言的一大利器。html
scala的pattern matching是相似这样的,java
e match { case Pattern1 => do Something case Pattern2 if-clause => do others ... }
其中,变量e后面接一个match以及一个代码块,其中每一个case对应一种可能回匹配的类型,若是匹配成功则执行=>后面的代码。算法
咱们能够用一个具体一些的例子来看看模式匹配是怎么工做的:数据结构
case class Player(name: String, score: Int) def printMessage(player: Player) = player match { case Player(_, score) if score > 100000 => println("Get a job, dude!") case Player(name, _) => println("Hey, $name, nice to see you again!") }
看起来有点相似于其余语言的switch,但其实仍是有很大的不一样的。app
以java的switch为例,java的switch仅仅会作一些基本类型的匹配,而后执行一些动做,而且是没有返回值的。ide
而scala的pattern matching match则要强大得多,除了能够匹配数值,同时它还能匹配类型。测试
def parseArgument(arg: String) = arg match { //匹配值 case "-h" | "--help" => displayHelp case "-v" | "--version" => displayVerion case whatever => unknownArgument(whatever) }
def f(x: Any): String = x match { //匹配类型 case i:Int => "integer: " + i case _:Double => "a double" case s:String => "I want to say " + s }
同时pattern matching是有返回值的,好比上面的match,它返回的就是一个Unit。咱们也能够修改上面的代码让它返回一个字符串:大数据
case class Player(name: String, score: Int) def message(player: Player) = player match { case Player(_, score) if score > 100000 => "Get a job, dude!" case Player(name, _) => "Hey, $name, nice to see you again!" }
值得一提的是,pattern matching 返回值是由第一个匹配的模式中的代码块决定的。ui
看到这里你会发现一个问题,pattern matching不是和if else差很少吗?那为何还要使用pattern matching呢?scala
首先咱们须要明白,模式匹配其实本质上是提供一个方便的解构(Destructuring)数据结构的方式,以scala为例,pattern matching其实用到了scala中提取器的功能,提取器其实就是类中的unapply()方法。
trait User { def name: String } class FreeUser(val name: String) extends User object FreeUser { //提取器 def unapply(user: FreeUser): Option[String] = Some(user.name) }
val user: User = new FreeUser("Daniel") user match { case FreeUser(name) => println("it match here" + name) case _ => println("not me") }
明白了模式匹配的本质你就会直到,其实if else只是pattern matching中的一个典型的用法,但并不是它的所有。
同时,pattern matching容许你解耦两个并不真正属于彼此的东西,也使得你的代码更易于测试。好比上面的match部分的代码咱们能够写成下面这样:
val user: User = new FreeUser("Daniel") //将返回结果存在一个常量中 val message = user match { case FreeUser(name) => "it match here" + name case _ => "not me" } //能够随意使用该常量,实现解耦 println(message)
这样会赋予代码更多的灵活性,同时也更加方便作进一步操做。
而以可读性的角度来讲,使用一大堆的if else代码无疑是比较难看的,而若是使用pattern matching的话,代码会简洁清晰不少,而简洁的代码则会更容易阅读。
参考文章:
https://doc.yonyoucloud.com/doc/guides-to-scala-book/chp3-pattern-everywhere.html
https://www.zhihu.com/question/30354775