聊聊 scala 的模式匹配

一. scala 模式匹配(pattern matching)

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

看到這裏你會發現一個問題, 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 的話,代碼會簡潔清晰不少,而簡潔的代碼則會更容易閱讀。

參考文章:


本文做者:終日而思一

閱讀原文

本文爲雲棲社區原創內容,未經容許不得轉載。

相關文章
相關標籤/搜索