5、Scala模式匹配
一、case class
用case修饰的Class 我们称之为Case Class。编译器看到这个case修饰的class,会为这个class加一些额外的特性:
1、编译器会为Case Class增加一个以类名为名字的工厂方法,这个工厂方法作用是构建这个类的对象
val v = Var("x") //构建对象的时候不需要用new关键词
2、编译器默认的为case class的值参数加上了val来进行修饰,所以这些值参数和一个类里的域一样
v.name
3、编译器自动为case class添加了toString、hashCode以及equals方法。可以用 == 来比较case class,比较case class的类型以及case class中的值参数
op.right == Var("x")
4、编译器为case class增加了一个copy方法,使得case class的值参数的值可以修改。如果一个case class中只要几个特定的值参数需要改变的话,用copy比较方便。
val opNew = op.copy(operator = "-")
case 除了可以修饰class,还可以修饰object,就是表示一个单例对象
case class最大的优点就是配合模式匹配
二、Scala的match表达式 和java switch区别
1、Scala的match表达式可以计算出一个值,而Java的switch却不能
2、模式匹配的表达式永远不会穿透到下一个case表达式中, java的switch中没有break的话,则会穿透到下一个分支
3、模式匹配中如果没有任何的模式被匹配到,则抛出MatchError异常
三、SealedClass
当你在用模式匹配的时候,你肯定需要考虑所有场景的case,有的时候我们可以用default来代替所有没有考虑到的情况,但是有的时候这个默认值没有意义,这个时候怎么来保证你能考虑到所有的情况呢?我们让编译器来帮我们考虑,我们可以在case class的父类上加一个sealed的关键字,这个sealed会帮我们做两件事情:
1:在我们定义模式匹配的时候,如果没有考虑全场景,编译器会报警告
2:被sealed修饰的类,不能被在其他文件中的case class继承
四、模式的种类
1、通配符模式 case _ 可以用于匹配默认的场景,可以用于可以忽略的对象的域的情况
2、常量模式
def describe(x: Any) = x match {
case 5 => "five"
case true => "truth"
case "hello" => "hi!"
case Nil => "the empty list"
case _ => "something else"
}
describe(5) //res6: String = five
describe(true) //res7: String = truth
describe("hello") //res8: String = hi!
describe(Nil) //res9: String = the empty list
describe(List(1, 2, 3)) //res10: String = something else
3、变量模式
可以将被匹配的表达式的值绑定到模式中的变量中,这样可以在expressions中使用这个变量
val i = 1 + 1
var result = i match {
case 0 => "zero"
case somethingElse => "not zero: " + somethingElse
}
println(result) // not zero: 2
编译器怎么判断是常量模式还是变量模式?
val pi = math.Pi
result = E match {
case pi => "strange math? Pi = " + pi //以小写字母开头的单词被编译器认为是变量模式
}
result = E match {
case `pi` => "strange math? Pi = " + pi //以反引号扩起来的为常量模式
case _ => "OK"
}
4、构造器模式。支持深度匹配
5、序列模式。支持固定长度的序列或者数组,也支持非固定长度。
v match {
case List(0, _*) => println("list it")//匹配含有任意个元素的List,并且第一个元素等于0
case Array(0, _*) => println("array it")//匹配含有任意个元素的Array,并且第一个元素等于0
case _ =>
}
6、元组模式
def tupleDemo(expr: Any) = expr match {
case (a, b, c) => println("matched " + a + b + c)
case _ =>
}
7、类型模式
def generalSizeWithPattern(x: Any) = x match {
case s: String => s.length
case m: Map[Int, Int] => m.size
case _ => -1
}
关于类型擦除,数组是个例外,因为数组在java中是特殊处理了,在scala中也是特殊处理了,在jvm中对应着不同类型的数组,比如int[], float[]等
isIntIntMap(Map(1 -> 1)) //true
isIntIntMap(Map("abc" -> "abc")) //true
isStringArray(Array("abc")) //yes
isStringArray(Array(1, 2, 3)) //no
8、变量绑定
val expr = UnOp("abs", UnOp("abs", Var("x")))
expr match {
case UnOp("abs", e@UnOp("abs", i@Var(_))) => println(e + " " + i)
case _ =>
}
五、模式守卫
在模式中可以定义条件。
def simplifyAdd(e: Expr) = e match {
case BinOp("+", a, b) if a == b => BinOp("*", b, Number(2))
case _ => e
}
六、模式重叠
尽量避免模式重叠
def simplifyBad(expr: Expr): Expr = expr match {
case UnOp("-", UnOp("-", e)) => e //第一个case
case UnOp(op, e) => UnOp(op, simplifyBad(e)) //第二个case
}
当case1属于case2的子集,那么case1可以放在case2之前,若放在case2之后,则永远无法执行,编译器会报警告unreachable code.
七、Option
Option视作一个容器,可以有东西,也可以没有东西。Some 表示有且仅有一个东西 None表示没有东西
val opt = Some("aaa")
opt.getOrElse("default")
在模式匹配中使用:
val capitals =
Map("France" -> "Paris", "Japan" -> "Tokyo")
def show(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
show(capitals get "Japan") //res25: String = Tokyo
show(capitals get "France") //res26: String = Paris
show(capitals get "North Pole") //res27: String = ?
八、模式在变量定义中的使用
val myTuple = (123, "abc")
val (number, string) = myTuple
val exp = new BinOp("*", Number(5), Number(1))
val BinOp(op, left, right) = exp
九、模式在偏函数中使用
1、一个case序列作为全函数(complete function)
val withDefault: Option[Int] => Int = {
case Some(x) => x
case None => 0
}
2、如果缺少了一个case会出现什么情况呢?编译会出现警告
val second: Option[Int] => Int = {
case Some(x) => x
}
3、如果我们的case列表是部分的场景,我们需要告诉编译器这是一个偏函数(partial function)
val partial : PartialFunction[Option[Int], Int] = {
case Some(x) => x
}
4、我们尽可能的用全函数,因为偏函数如果没有考虑清楚需要处理的case的话,可能会抛异常。
上面的partial就是和下面的p是一个意思
val p = new PartialFunction[Option[Int], Int] {
override def isDefinedAt(x: Option[Int]) = x match {
case Some(_) => true
case None => false
}
override def apply(v1: Option[Int]) = v1 match {
case Some(x) => x
}
5、如果要使用偏函数,推荐用下面模式
if (partial.isDefinedAt(None)) {
partial(None) //如果单独运行的话,还是会抛异常
}
十、模式在for中使用
val results = List(Some("apple"), None, Some("orange"))
for (Some(fruit) <- results) println(fruit)
val capitals =
Map("France" -> "Paris", "Japan" -> "Tokyo")
for ((country, city) <- capitals)
println("The capital of " + country + " is " + city)
十一、萃取器unapply
含有成员方法unapply的object,我们称之为extractors(萃取器)。extractors可以同时定义apply(可选的)和unapply方法。
转载于:https://blog.51cto.com/13921538/2299797
5、Scala模式匹配相关推荐
- Scala模式匹配的亮点——Martin Odersky访谈(四)
Martin Odersky向Bill Venners和Frank Sommers谈论Scala模式匹配的机制和目的. \\ Scala是一种新兴的通用用途.类型安全的Java平台语言,结合了面向对象 ...
- Scala模式匹配和类型系统
Scala模式匹配和类型系统 1.模式匹配比java中的switch case强大很多,除了值,类型,集合等进行匹配,最常见的Case class进行匹配,Master.scala有大量的模式匹配. ...
- Scala模式匹配--样例类--密封样例类--偏函数
Scala模式匹配--样例类--密封样例类--偏函数 模式匹配 等价于java的switch caseval c = '+'c match{case '+' => println(111)cas ...
- scala 模式匹配 match
文章目录 一.match 基本介绍 二.match 的细节和注意事项 三.模式匹配之条件守卫 四.模式匹配之变量匹配.常量匹配 五.模式匹配之类型匹配 六.模式匹配之数组匹配 七.模式匹配之集合匹配 ...
- scala 模式匹配
Scala 中的模式匹配类似于 Java 中的 switch 语法 1 基本语法 模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需 要匹配时,会从第一个 ca ...
- Scala模式匹配详解
前言 Scala 中的模式匹配类似于 Java 中的 switch 语法 Java中的switch语法,default就是都不符合 int i = 10 switch (i) {case 10 :Sy ...
- Scala模式匹配,case 字符串,case 匹配类型,case 匹配数组,case 匹配List,case 匹配元组,case匹配case class和case object
一. 模式匹配和样例类 Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句.类型检查等. 并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配 1. 匹配字 ...
- scala 模式匹配详解 1
什么是模式? 一些刚从java转到scala的同学在开发的过程中犹如深陷沼泽,因为很多的概念或风格不确定,scala里有很多的坑,模式匹配也算一个.我整理了一下自己所理解的概念,以及一些例子.这个系列 ...
- scala 模式匹配概念及用法示例
概念 可以理解为升级版的java switch 1 java中的switch -case是一个分支结构,用于匹配整型(byte,short,int,char),字符串,枚举. (long类型不可以) ...
最新文章
- python凯撒密码详解_Python基础题目集--课堂案例
- JAVA基础3-选择语句
- java-二分查找树的实现
- Python Day 21 面向对象 (面向对象的三大特性(二)继承,多态,封装,几个装饰器函数)...
- 2000年考研英语阅读理解文章三
- python怎么执行csv文件_无法读取/打开/或对CSV文件python 3.4windows执行任何操作
- 6.第一个程序Hello World
- python解acm题_python ACM ,持续更新中。。。。。。。。。。。。
- mysql router 多台写入_Centos7部署MySQL-router实现读写分离及从库负载均衡
- python3数据结构菜鸟教程_Python3
- 快速对表的某字段赋递增的数值
- PGIS 天地图主题颜色背景修改 图片 filter 蓝色 HTML CSS IMG filter 颜色矩阵在线计算 RGBA转换 SVG feColorMatrix
- 新晋院士!顶尖985,迎来新校长!
- java输入输出流实例代码
- 环境试验之单臂跌落试验机操作规程
- 在vscode中php语言配置,vscode配置go语言开发环境
- 2022虎符线上团队赛 有关web的部分题解(持续更新)
- NW.js之基础篇(2)
- 如何安装Eclipse WTP插件
- 湖北专升本MySQL复习(MySQL数据库实用教程)——MySQL数据表的操作
热门文章
- 大跌眼镜!杭州一程序员年薪 30 万,竟靠偷车厘子缓解压力?
- 程序员如何乘风破浪?从数据库历史看技术人发展 | CSDN 高校俱乐部
- 浏览器访问网页过程中发生了什么?(转)
- 『原创』+『参考』基于PPC的图像对比程序——使用直方图度量
- Hotel California
- 2011年 软件所信息安全国家重点实验室复试回忆
- MyBatis学习总结(9)——使用MyBatis Generator自动创建代码
- TCP三次握手,四次分手
- pytorch读取文本训练
- PowerDesigner打开设计文件后提示failed to read the fileXXX的解决办法