模式匹配是scala中非常有特色, 非常強大的一種工. 模式匹配, 其實類似於java的switch語法, 即對一個值進行判斷, 然後針對不同的條件, 進行不同的處理.
但是scala的模式匹配的功能比java的switch語法的功能強很多, java的只能對值進行匹配, 還是隻能int和列舉的值進行匹配. 但是scala的模式匹配除了可以對值進行匹配外, 還可以有以下匹配:
- 對型別進行匹配
- 對Array和List的元素情況進行匹配
- 對case class進行匹配
- 有值或沒值(Option)進行匹配.
簡單例子
scala是沒有java的switch語法, 但提供更強大的match語法, 即模式匹配.
match語法如下: 變數名 match{case 值 => 表示式}
如果值為下劃線, 則表示不滿足以上所有情況的預設情況處理.
match語法中, 只要一個case分支滿足, 則不會繼續判斷下一個case分支. 這一點跟java不一樣, 也避免了忘記寫break造成的bug.
例子: 成績評價
def judgeGrade(grade: String){
grade match{
case "A" => println("Excellent")
case "B" => println("Good")
case "C" => println("Just so so")
case _ => println("you need work harder")
}
}
在模式匹配中使用if守衛
scala的模式匹配語法, 有一個特點在於, 可以在case後的條件判斷中, 不僅僅只是提供一個值, 而是可以在值後面再加一個if守衛, 進行雙重過濾.
例子: 成績評價(升級版, 可根據名稱給出不同的提示)
def judgeGrade(name:String, grade:String){
grade match{
case "A" => println(name+", you are excellent")
case "B" => println(name+", you are good")
case "C" if name == "jc" => println(name+", you are a good boy, come on")
case "C" => println(name+", you are just so so") //這句必須是在上一句的後面, 不然就永遠匹配不到jc
case _ => println("you need to work harder")
}
}
在模式匹配中進行變數賦值
scala的模式匹配語法, 可以將模式匹配的預設情況, 下劃線, 替換為一個變數名, 此時模式匹配語法就會將要匹配的值賦值給這個變數, 從而可以在後面的處理語句中使用被匹配的值.
例子: 成績評價(升級版, 可根據名稱給出不同的提示, 並且帶成績)
def judgeGrade(name:String, grade:String){
grade match{
case "A" => println(name+", you are excellent")
case "B" => println(name+", you are good")
case "C" => println(name+", you are just so so")
case _actualGrade if name == "jc" => println(name+", you are a good boy, come on, your grade is "+_actualGrade)
case _actualGrade => println("you need to work harder, your grade is"+_actualGrade)
}
}
對型別進行模式匹配
scala的模式匹配其中一個強大功能就是, 可以直接匹配型別.
例子: 異常處理
import java.io_
def processException(){
e match{
case e1: IllegalArgumentException=> println("that has illegal arguments! exception is: "+e1)
case e2: FileNotFoundException=> println("can not find the file! exception is: "+e2)
case e3: IOException=> println("you got an IOException")
case _: Exception=>println("I have not idea what exception is")
}
}
注意這裡要與上面的”模式匹配對值的匹配”進行對比, 知道它們的差異, 匹配值是 case 值=> 表示式, 而匹配型別是case 變數: 型別=>表示式. 所以匹配型別預設就可以進行變數賦值. 而匹配值則需要以下劃線來定義新的變數來賦值.
對Array和List進行模式匹配
對Array進行模式匹配, 分別可以匹配帶有指定元素的陣列, 帶有指定元素個數的陣列, 指定以某個元素打頭的陣列
對List進行模式匹配, 跟Array類似, 但是需要List特有的::操作符
例子: 對朋友打招呼
def greeting(peoples: Array[String]){
peoples match{
case Array("jc")=> println("Hi, jc!")
case Array(girl1, girl2, girl3)=> println("Hi, girls, nice to meet you. "+girl1+" and "+girl2+" and "+ girl3)
case Array("jc",_*)=> println("Hi, jc, please introduce your friends to me.")
case _=> println("hey guys, who are you!")
}
}
var a = Array("jc")
greeting(a)
a = Array("jc","jay","jack")
greeting(a)
a = Array("jc","jay","jack","john")
greeting(a)
a = Array("jay","jack","john","johnny")
greeting(a)
def greeting(peoples: List[String]){
peoples match{
case "jc"::Nil=> println("Hi, jc!")
case girl1::girl2::girl3::Nil=> println("Hi, girls, nice to meet you. "+girl1+" and "+girl2+" and "+girl3)
case "jc"::tail=> println("Hi, jc, please introduce your friends to me.")
case _=> println("hey guys, who are you!")
}
}
var a = List("jc")
greeting(a)
a = List("jc","jay","jack")
greeting(a)
a = List("jc","jay","jack","john")
greeting(a)
a = List("jay","jack","john","johnny")
greeting(a)
上面兩個功能都一樣, case語句分別是一下功能: 只有jc元素的, 3個元素的集合, jc元素的打頭的, 其他情況的.
case class與模式匹配
scala提供了一種特殊的累, 就是用case class的類, 這種類稱為樣例類. 樣例類其實有點類似於嚴格定義的JavaBean, 只定義了field, 並且由scala編譯時自動提供getter和setter方法, 但是沒有其他方法.
除此之外,scala會自動為樣例類定義伴生物件, 也就是object, 並且定義了apply方法, 該apply方法的引數跟主建構函式的引數一樣, 病返回樣例類.
簡單的說, 樣例類簡化了定義類和例項化類的語法.
例子: 學校廣播
class Person
case class Teacher(name:String, subject:String) extends Person
case class Student(name:String, classroom:String) extends Person
def broadcast(p: Person){
p match{
case Teacher(name, subject)=> println("教"+subject+"的"+name+"老師馬上到教導處來")
case Student(name, classroom)=> println(classroom+name+"馬上到教導處來")
case _=>println("三年二班")
}
}
val t = Teacher("周杰倫","音樂")
val s = Student("周杰倫","三二班")
broadcast(t)
broadcast(s)
Option與模式匹配
scala有一種特殊的型別叫Option, Option有兩個值, 一種是Some, 代表有值, 一種是None代表沒有值.
Option通常會用於模式匹配中, 用於判斷某個變數是否有值還是沒有值, 這比null來的更加語義化.
例子: 成績查詢
val grades = Map("jc"->"A","jay"->"B","jack"->"M")
def getGrade(name:String){
var grade = grades.get(name)
grade match{
case Some(grade)=> println("Hi "+name+", your grade is "+grade)
case None=> println("Sorry "+name+", your grade is not in the system.")
}
}
getGrade("jc")
getGrade("jay")
getGrade("jack")
getGrade("john")