模式匹配

昵称已经被使用 / 2023-08-13 / 原文

第14章 模式匹配

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

模式匹配有点像一个别致的switch声明,它可以侵入到表达式数据结构内部,对这个结构进行检验和提取子表达式。如果没有模式能够匹配,会抛出MatchError。可以用case_模式来避免。

它由一个表达式引入,例如 ds 后边紧跟一个关键字match和一个用花括号封起来的一系列的case 语句,每一条case 语句由=> 箭头右边的模式(Cons(x,xs))和=>箭头右边的结果(x*product(xs))组成。如果目标匹配其中一种模式,它的结果就是整个match表达式的结果。如果目标与多个模式都匹配,Scala 选择第一个匹配的结果。

Ø模式可以当作对某个类型,其内部数据在结构上抽象出来的表达式。模式匹配(pattern-matching)则是匹配变量是否符合这种pattern。

看如下例子

匹配一个数组,它由三个元素组成,第一个元素为1,第二个元素为2,第三个元素为3

Array(1,2,3) match (case Array(1,2,3) => println("ok"))

常量模式(constant patterns):包含常量变量和常量字面量。

def foo(s: String): String = s match {
    case "ESOFT" => "HBD BigData"
    case _ => "I don't know "
  }

变量模式(variable patterns):确切的说单纯的变量模式没有匹配判断的过程,只是把传入的对象给起了一个新的变量名。

println("输入点啥:")
var temp = scala.io.StdIn.readLine()
temp match {
	case whateverName => println(whateverName)
}

通配符模式(wildcard patterns):通配符用下划线表示:“_” ,可以理解成一个特殊的变量或占位符。单纯的通配符模式通常在模式匹配的最后一行出现,case _ => 它可以匹配任何对象,用于处理所有其它匹配不成功的情况。通配符模式也常和其他模式组合使用。

def wildcardMatch(array: Array[Int]): String = array match{
    case Array(_,_,3) => "succ"
    case _ => "fail"
}

构造器模式(constructor patterns):非常好用,真正能体现模式匹配威力的模式,通过构造函数匹配对象

val tree = Tree(TreeNode("root",TreeNode("left",null,null),TreeNode("right",null,null)))
     //希望构造一个节点 左子节点值为”left”,右子节点值为”right”并且右子节点没有子节点
     
     tree.root match {
       case TreeNode("root", TreeNode("left",_,_), TreeNode("right", null, null))
       =>
       println("ok")
       case _ => println("error")
	}

类型模式(type patterns):类型模式很简单,就是判断对象是否是某种类型, isInstanceOf 判断类型的效果一样(Scala提倡使用模式匹配),需要注意的是scala 匹配泛型时要注意,如果使用了泛型,它会被擦拭掉,无法准确匹配泛型内部的内容

def foo(a: Any): String = a match {
    //只能检查包装,检查不了里面的货物一次 下面这行应当这样写List[_]
    case a: List[Int] => "OK"
    case _ => "fail"
}