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 對應一種可能回匹配的類型,若是匹配成功則執行 => 後面的代碼。數據結構
咱們能夠用一個具體一些的例子來看看模式匹配是怎麼工做的:app
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,但其實仍是有很大的不一樣的。ide
以java 的 switch 爲例,java 的 switch 僅僅會作一些基本類型的匹配,而後執行一些動做,而且是沒有返回值的。測試
而 scala 的 pattern matching match 則要強大得多,除了能夠匹配數值,同時它還能匹配類型。ui
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。咱們也能夠修改上面的代碼讓它返回一個字符串:scala
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 返回值是由第一個匹配的模式中的代碼塊決定的。code
看到這裏你會發現一個問題, pattern matching 不是和if else 差很少嗎?那爲何還要使用 pattern matching 呢?htm
首先咱們須要明白,模式匹配其實本質上是提供一個方便的解構 (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 的話,代碼會簡潔清晰不少,而簡潔的代碼則會更容易閱讀。
參考文章:
本文做者:終日而思一
本文爲雲棲社區原創內容,未經容許不得轉載。