scala--模式匹配

1. 模式匹配

1、模式匹配是Scala中非常强大的一种功能。模式匹配,其实类似于Java中的switch case语法,即对一个值进行条件判断,然后针对不同的输入条件,进行结果处理。
2、Scala的模式匹配的功能比Java的switch case语法的功能要强大地多,Java的switch case语法只能对值进行匹配。但是Scala的模式匹配除了可以对值进行匹配之外,还可以对类型进行匹配、对Array和List的元素情况进行匹配、对case class进行匹配、甚至对有值或没值(Option)进行匹配。

​ 模式匹配常见的语法结构如下:

​ 变量 match {

​ case 可能性1 => 操作1

​ 。。。

​ case 可能性N => 操作N

​ case _ => 默认/其它操作

​ }

1.1. 可以用到Switch语句中

Scala强大的模式匹配机制,可以应用在switch语句、类型检查以及“析构”等场合。

//使用模式匹配完成switch的操作
var sign = 0
val ch = '+'
ch match {
    case '-' => sign = -1
    case '*' => sign = -2
    case '+' => sign = 0
    case _ => sign = 1
}
/*
         * switch(ch) {
         *  case '+' :
         *    sign = 0;
         *    break;
         *  case '-' :
         *    sign = -1;
         *    break;
         *  case '*' :
         *    sign = -2;
         *    break;
         *  default:
         *    sign = 1;
         *    break;
         * }
         */
println("sign=" + sign)
//scala中的每一个表达式都有返回值,默认最后一句话就是返回值
sign = ch match {
    case '-' => -1
    case '*' => -2
    case '+' =>  0
    case _ => 1
}
println("sign=" + sign)

1.2. 守卫

像for表达式一样,match也提供守卫功能,守卫可以是任何Boolean条件 match 守卫功能

def caseOps2: Unit = {
        var sign = 0
        val ch = '-'
        val ret = ch match {
            case '-' => sign = -1
            case '*' => sign = -2
            case _ if Character.isDigit(ch) => 3
            case _ => sign = 1
        }
        println("ret = " + ret)
    }

1.3. 模式中的变量和类型模式

​ 模式匹配中的变量,需要从语法结构说起:

变量 match {

​ case 可能性1 => 操作1

​ 。。。

​ case 可能性N => 操作N

​ case _ => 默认/其它操作

​ }

启动如果是匹配的类型,可以将可能性x书写为==> 变量:类型,可能性以就成为=>变量1:类型1,这样做的好处是什么呢?就是直接进行类型转换,可以方便操作其特有的api。

​ 如果类型时确定的,可以将:后面的类型省略掉。

  • 变量

    def caseOps3: Unit = {
        "Hello world~".foreach(c => println(
            c match {
                case ' ' => "space"
                case ch => "Char: " + ch
            }
        ))
    }
    
  • 类型

    val input:Any = StdIn.readLine("请输入内容:")
    //        input.isInstanceOf
    //        input.asInstanceOf
    input match {
        case i:Int => println("int i = " + i)
        case s:String => println("String s = " + s)
        case ch:Char => println("char ch = " + ch)
        case _ => println(input)
    }
    

1.4. 匹配数组、列表和元组

val array = Array(0, -5)
array match {
    //匹配数组有2个元素,分别将两个元素赋值给x和y
    case Array(x, y) => println(s"x=$x, y=$y")
    //匹配数组以0开头
    case Array(0, _*) => println("Array(0, _*)")
    //默认的匹配,如果匹配不到,scala.MatchError
    case _ => println("default")
}

1.5. 样例类

​ 所谓样例类,就是case class,是scala中一种专门用来携带数据的class,类似于java中的javabean,一般的定义方式需要定义该case class的主构造器,其所有的字段都在主构造器中完成声明,case class自动会提供所谓getter和setter方法。

​ case class的主构造函数接收的参数通常不需要使用var或val修饰,Scala自动就会使用val修饰(但是如果你自己使用var修饰,那么还是会按照var来)
​ Scala自动为case class定义了伴生对象,也就是object,并且定义了apply()方法,该方法接收主构造函数中相同的参数,并返回case class对象

def caseOps6: 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
    case class BinOp(left:Expr, operator:String, right:Expr) extends Expr

    def test(expr:Expr) = {
        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 _ => println(expr)
        }
    }

    test(BinOp(Number(3.0), "-", Number(5.2)))
}

1.6. 模拟枚举

  • 枚举的一般定义方式

    object _02EnumrationOps {
        def main(args: Array[String]): Unit = {
           def accrossRoad(light: TrafficLight.Value): Unit = {
               light match {
                   case TrafficLight.GREEN => println("畅行无阻,及时通过")
                   case TrafficLight.YELLOW => println("hurry up")
                   case TrafficLight.RED => println("行车不规范,亲人泪两行")
                   case _ => println("翻车了")
               }
           }
    
            accrossRoad(TrafficLight.GREEN)
        }
    }
    //普通的枚举的定义
    object TrafficLight extends Enumeration {
        val GREEN, YELLOW, RED = Value
    }
    
  • 枚举的模式匹配方式

    sealed class密封类,一个类的所有的子类型都是已知的,都必须要在定义期间给出
    当然一般这个sealed class密封类通常会被声明为抽象,使用子类来完成具体构建
    密封类的所有子类都必须在与该密封类相同的文件中定义。
    如果某个类是密封的,那么在编译期所有的子类是可知的,因而可以检查模式语句的完整性。
    让所有同一组的样例类都扩展某个密封的类或特质是个好的做法。
    
    sealed abstract class TrafficLight(color:String)
    case class RED(red:String) extends TrafficLight(red)
    case class GREEN(green:String) extends TrafficLight(green)
    case class YELLOW(yellow:String) extends TrafficLight(yellow)
    
    val light:TrafficLight = RED("酒后来驾车,亲人泪两行")
    light match {
        case RED(red) => println(red)
        case GREEN(green) => println(green)
        case YELLOW(yellow) => println(yellow)
    }
    

1.7. Option

​ Option是scala中有值(Some)或者没有值(None)的类型,scala也可以对应Option进行模式匹配进行处理。

val map = Map[String, String](
	"China" -> "BJ",
    "India" -> "XDL",
    "Japan" -> "Tokyo"
)

map.get("India") match {
    case Some(capital) => println("India's capital is " + capital)
    case None => println("所查国家不存在")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值