Scala深入学习之模式匹配

简介: 模式匹配是检查某个值(value)是否匹配某一个模式的机制,一个成功的匹配同时会将匹配值解构为其组成部分。它是Java中的switch语句的升级版,同样可以用于替代一系列的 if/else 语句。

一、语法


一个模式匹配语句包括一个待匹配的值,match关键字,以及至少一个case语句。

package matchDemo.mode
import scala.io.StdIn
/**
 * @author : 蔡政洁
 * @email :caizhengjie888@icloud.com
 * @date : 2020/11/17
 * @time : 12:35 下午
 * 完成Scala中模式匹配的学习
 */
object MatchCaseOps1 {
    def main(args: Array[String]): Unit = {
        // swichOps()
        // yeildOps() // 简写
        // typeOps() // 类型的模式匹配
        collectionOps() // 集合操作
    }
    /*
     * 学习模式匹配去模拟Java中的switch语法
     * char ch = '='
     * switch(ch){
     *      case '+'
     *          ...
     *          break;
     *      case '-'
     *          ...
     *          break;
     *      ...
     *      default:
     *          ...
     *          break;
     * }
     *
     */
    def swichOps(): Unit ={
        println("请从控制台输入一个字符:")
        val ch:Char = StdIn.readChar()
        var sign = 0
        ch match {
            case '+' => sign = -1
            case '-' => sign = 1
            case '*' => sign = -2
            case '/' => sign = 2
            case _ => sign = 0 // Java中default操作
        }
        println("sign:"+sign)
    }
    // 模式匹配是一个表达式,因此是有返回值的
    def yeildOps(): Unit ={
        println("请从控制台输入一个字符:")
        val ch:Char = StdIn.readChar()
        var sign = ch match {
            case '+' =>  -1
            case '-' =>  1
            case '*' =>  -2
            case '/' =>  2
            case _ =>  0 // Java中default操作
        }
        println("sign:"+sign)
    }
    def typeOps(): Unit ={
        class Person(name:String,age:Int){
        }
        class Worker(name:String,age:Int) extends Person(name,age){
            def work(): Unit ={
                println(s"工人${name},年龄为${age}正在工作")
            }
        }
        class Student(name:String,age:Int) extends Person(name,age){
            def study(): Unit ={
                println(s"学生${name},年龄为${age}正在学习")
            }
        }
        def doSth(person: Person): Unit ={
            // 类型匹配--类型检查
            person match {
                case worker: Worker => worker.work()
                case student: Student => student.study()
                case _ => println("没有匹配到具体类型")
            }
        }
        doSth(new Worker("alex",23))
    }
    def collectionOps(): Unit ={
        println("----------匹配字符串----------")
        val str = "hello world"
        for (ch <- str){
            ch match {
                case ' ' => println(",")
                case _ => println(ch)
            }
        }
        println("----------匹配其他集合----------")
        val array = Array(0,1)
        array match {
            // 匹配当前数组,如果只有两个元素,成功,就依次赋值给x,y
            case Array(x,y) => println(s"x=${x},y=${y}")
            case Array(0,_ *) => println("匹配该数组,首元素为0")
            case _ => println("other.")
        }
    }
}


二、案例类


案例类非常适合用于模式匹配。示例代码:

package matchDemo.mode
/**
 * @author : 蔡政洁
 * @email :caizhengjie888@icloud.com
 * @date : 2020/11/17
 * @time : 1:33 下午
 * 模式匹配之匹配case class样例类
 */
object MatchOps2 {
    def main(args: Array[String]): Unit = {
        caseOps()
    }
    def caseOps(): Unit ={
        abstract class Expr // 抽象类,代表了表达式
        case class Var(name:String) extends Expr
        case class UnOp(expr: Expr,operator: String) extends Expr
        case class Number(num:Double) extends Expr
        // 3+4
        case class BinOp(val left: Expr,operator: String,var right: Expr) extends Expr
        def test(expr: Expr): Unit ={
            expr match {
                case  Var(name) => println("var:"+name)
                case Number(num) => println("number:"+num)
                case UnOp(Var(name),"+") => println(name + "+")
                case BinOp(Number(num1),"+",Number(num2)) => println(num1+num2)
                case BinOp(Number(num1),"-",Number(num2)) => println(num1-num2)
                case BinOp(Number(num1),"*",Number(num2)) => println(num1*num2)
                case BinOp(Number(num1),"/",Number(num2)) => println(num1/num2)
                case _ => println(expr)
            }
        }
        val binOp = BinOp(Number(3.0),"*",Number(4.2))
        binOp.right = Number(3.2)
        test(binOp)
    }
}

运行结果:

9.600000000000001


三、密封类


特质(trait)和类(class)可以用sealed标记为密封的,这意味着其所有子类都必须与之定义在相同文件中,从而保证所有子类型都是已知的。

package matchDemo.mode
/**
 * @author : 蔡政洁
 * @email :caizhengjie888@icloud.com
 * @date : 2020/11/17
 * @time : 2:12 下午
 * Scala中使用case class来模拟枚举操作
 */
object EnumerationOps {
    def main(args: Array[String]): Unit = {
        accrossRoad(TrafficLight.GREEN)
        println("------使用case class来模拟枚举------")
        accrossRoad(RED("hongdeng"))
    }
    def accrossRoad(ligth:TrafficLight.Value): Unit ={
        ligth match {
            case TrafficLight.RED => println("行车不规范,亲人两行泪")
            case TrafficLight.YELLOW => println("快人5秒钟,快人一辈子")
            case TrafficLight.GREEN  => println("开开心心开出去,平平安安开回来")
        }
    }
    def accrossRoad(ligth:Light): Unit ={
        ligth match {
            case RED(name) => println(name+"行车不规范,亲人两行泪")
            case YELLOW(name) => println(name+"快人5秒钟,快人一辈子")
            case GREEN(name)  => println(name+"开开心心开出去,平平安安开回来")
        }
    }
    // 使用Scala传统的方式来定义一个枚举,得到RED其实是TrafficLight.Value这种类
    object TrafficLight extends Enumeration{
        val RED,YELLOW,GREEN = Value
    }
}
/*
scala中对于如果说一个类的子类都是已知的,我们可以使用一个sealed关键字来进行修饰
表示该类是密封,刚好和枚举类含义契合,枚举,可以,一一列举
 */
sealed class Light(name:String)
case class RED(name:String) extends Light(name)
case class YELLOW(name:String) extends Light(name)
case class GREEN(name:String) extends Light(name)

运行结果:

开开心心开出去,平平安安开回来
------使用case class来模拟枚举------
hongdeng行车不规范,亲人两行泪


四、option操作


package matchDemo.mode
/**
 * @author : 蔡政洁
 * @email :caizhengjie888@icloud.com
 * @date : 2020/11/17
 * @time : 2:31 下午
 * scala模式匹配之option操作
 */
object MatchOps3 {
    def main(args: Array[String]): Unit = {
        val map = Map[String,String](
            "China"->"Beijing",
            "Japan"->"Tokyo",
            "India"->"XDL"
        )
        val capitalOption:Option[String] = map.get("China")
        capitalOption match {
            case Some(capital) => println("Capital is"+capital)
            case None => println("所查国家不存在")
        }
    }
}

运行结果:

Capital isBeijing
相关文章
|
8月前
|
Scala
166 Scala 模式匹配和样例类
166 Scala 模式匹配和样例类
59 0
|
17天前
|
Scala
scala-模式匹配(字符串、数组、元组、集合、类、偏函数)
scala-模式匹配(字符串、数组、元组、集合、类、偏函数)
9 0
|
2月前
|
Scala 容器
Scala学习--day04--集合、常用方法、案例实操 - WordCount TopN、不同省份的商品点击排行
Scala学习--day04--集合、常用方法、案例实操 - WordCount TopN、不同省份的商品点击排行
|
2月前
|
消息中间件 分布式计算 大数据
Scala学习--day03--函数式编程
Scala学习--day03--函数式编程
|
2月前
|
Java Scala
Scala学习--day02---控制流、“九层妖塔—杨辉三角”
Scala学习--day02---控制流、“九层妖塔—杨辉三角”
113 1
|
2月前
|
Java 编译器 API
Scala学习--day01变量与数据类型、运算符
Scala学习--day01变量与数据类型、运算符
|
2月前
|
Scala
Scala中的异常处理和模式匹配
Scala中的异常处理和模式匹配
24 1
|
2月前
|
Scala
Scala中的模式匹配:强大的匹配和转换工具
Scala中的模式匹配:强大的匹配和转换工具
26 1
|
2月前
|
分布式计算 Java 大数据
Scala:样例类、模式匹配、Option、偏函数、泛型(三)
Scala:样例类、模式匹配、Option、偏函数、泛型(三)
59 0