2018年第46周-scala入门-模式匹配

萧然 2019-06-29

模式匹配是scala中非常有特色, 非常强大的一种工. 模式匹配, 其实类似于java的switch语法, 即对一个值进行判断, 然后针对不同的条件, 进行不同的处理.
但是scala的模式匹配的功能比java的switch语法的功能强很多, java的只能对值进行匹配, 还是只能int和枚举的值进行匹配. 但是scala的模式匹配除了可以对值进行匹配外, 还可以有以下匹配:

  1. 对类型进行匹配
  2. 对Array和List的元素情况进行匹配
  3. 对case class进行匹配
  4. 有值或没值(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")

相关推荐

kekeromer / 0评论 2020-04-30