模式匹配(match case)

Scala没有Java中的switch case语法,但是,Scala提供了更加强大的match case语法,即模式匹配
对一个值进行条件判断,然后针对不同的条件,进行不同的处理

Java的switch case仅能匹配变量的值,而Scala的match case可以匹配各种情况,比如:变量的类型、集合的元素,有值没值

对变量的值

match case语法格式:变量 match { case 值 => 代码 }
如果值为下划线,则代表了不满足以上所有情况下的默认处理

  1. def convertDay(day: Int): Unit = {
  2. day match {
  3. case 1 => println("Monday")
  4. case 2 => println("Tuesday")
  5. case 3 => println("Wednesday")
  6. case _ => println("none")
  7. }
  8. }
  9. def main(args: Array[String]): Unit = {
  10. convertDay(1)
  11. convertDay(2)
  12. convertDay(3)
  13. convertDay(5)
  14. }

image.png

对变量类型

语法格式:变量 match { case 变量: 类型 => 代码 }
典型的一个应用场景就是针对异常的处理

  def processException(e: Exception): Unit = {
    e match {
      case e: IllegalArgumentException => println("IllegalArgumentException  " + e)
      case e: FileNotFoundException => println("FileNotFoundException  " + e)
      case e: IOException => println("IOException " + e)
      case _: Exception => println("Exception ")
    }
  }

  def main(args: Array[String]): Unit = {
    processException(new Exception())
    processException(new IOException())
  }

image.png

try-catch

在try-catch异常中的应用

  def main(args: Array[String]): Unit = {

    try {
      val lines = scala.io.Source.fromFile("D://test02.txt").mkString
    } catch {
      case e: FileNotFoundException => println("no file: " + e)
      case e: IOException => println("io exception")
      case e: Exception => println("exception")
    }

  }

image.png

case class(样例类)

Scala中提供了一种特殊的类,用case class进行声明,中文可以称为样例类
case class其实有点类似于Java中的JavaBean的概念
即只定义field,会由Scala在编译时自动提供get和set方法,但是没有其它的method
case class的主构造函数接收的参数通常不需要使用var或val修饰,Scala自动就会使用val修饰(但是如果你自己使用var修饰,那么还是会按照var来,在这用哪个区别都不大)
Scala自动为case class定义了伴生对象,也就是object,并且定义了apply()方法,该方法接收主构造函数中相同的参数,并返回case class对象
下面来看一个案例:
先定义三个class

class Person     
case class Teacher(name: String, sub: String) extends Person     
case class Student(name: String, cla: String) extends Person

再创建一个函数

def check(p: Person) {     
  p match {     
    case Teacher(name, sub) => println("Teacher, name is " + name + ", sub is " + sub)     
    case Student(name, cla) => println("Student, name is " + name + ", cla is " + cla)     
    case _ => println("none")     
  }       
}

执行

scala>  check(new Student("tom","class1"))     
Student, name is tom, cla is class1     

scala>  check(new Person())     
none

Option

Scala有一种特殊的数据类型,叫做Option。
Option有两种值,一种是Some,表示有值,一种是None,表示没有值
Option通常会用于模式匹配中,用于判断某个变量是有值还是没有值,这比null来的更加简洁明了

map的get方法返回的就是Option

scala> val ages = Map("jack" -> 18, "tom" -> 30, "jessic" -> 27)
ages: scala.collection.immutable.Map[String,Int] = Map(jack -> 18, tom -> 30, jessic -> 27)

scala> ages.get("jack")
res20: Option[Int] = Some(18)

scala> ages.get("jack2")
res21: Option[Int] = None

看这个案例

val ages = Map("jack" -> 18, "tom" -> 30, "jessic" -> 27)     

def getAge(name: String) {     
  val age = ages.get(name)     
  age match {     
    case Some(age) => println("your age is " + age)     
    case None => println("none")     
  }     
}

执行

scala> getAge("jack")     
your age is 18     

scala> getAge("hehe")     
none

隐式转换(implicit)

Scala的隐式转换,允许手动指定将某种类型的对象转换成其它类型的对象
Scala的隐式转换,最核心的就是定义隐式转换函数,即implicit conversion function
隐式转换函数与普通函数唯一的语法区别是要以implicit开头而且最好要定义函数返回类型
隐式转换非常强大的一个功能,就是可以在不知不觉中加强现有类型的功能。也就是说,我们可以为某个普通类定义一个加强类,并定义对应的隐式转换函数,这样我们在使用加强类里面的方法的时候,Scala会自动进行隐式转换,把普通类转换为加强类,然后再调用加强类中的方法
Scala默认会自动使用两种隐式转换
1:源类型,或者目标类型的伴生对象里面的隐式转换函数
2:当前程序作用域内可以用唯一标识符表示的隐式转换函数
如果隐式转换函数不在上述两种情况下的话,那么就必须手动使用import引入对应的隐式转换函数
通常建议,仅仅在需要进行隐式转换的地方,比如某个函数内,用import导入隐式转换函数,这样可以缩小隐式转换函数的作用域,避免不需要的隐式转换

案例:狗也能抓老鼠

通过隐式转换实现,狗也具备猫抓老鼠的功能

class cat(val name: String){     
  def catchMouse(){println(name+" catch mouse")}     
}     
class dog(val name: String)     

implicit def object2Cat (obj: Object): cat = {     
  if (obj.getClass == classOf[dog]) {      
    val dog = obj.asInstanceOf[dog]     
    new cat(dog.name)     
  }     
  else Nil     
}

执行

scala> val d = new dog("d1")     
d: dog = dog@7f0e0db3     

scala> d.catchMouse()     
d1 catch mouse

我们在工作中一般很少需要我们自己去定义隐式转换函数,大部分的场景是我们只需要使用import导入对应的隐式转换函数就可以了,在这个案例中我们是自己手工实现了一个隐私转换函数,因为他们都在一个作用域内,所以就不需要import了。