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對應一種可能回匹配的類型,若是匹配成功則執行=>後面的代碼。算法

咱們能夠用一個具體一些的例子來看看模式匹配是怎麼工做的:數據結構

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

看到這裏你會發現一個問題,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


推薦閱讀:
從分治算法到 MapReduce
大數據存儲的進化史 --從 RAID 到 Hdfs

相關文章
相關標籤/搜索