欢迎关注我的新博客地址:http://cuipengfei.me/

实在想不到什么动词可以当做脱衣服来讲了,所以从现在开始这系列博文就叫做Desugar Scala了。除非哪天才思泉涌,又想到了新词:)

开始正文。

名字叫做unapply和unapplySeq的方法在Scala里也是有特殊含义的。

我们前面说过case class在做pattern match时很好用,而除case class之外,有unapply或unapplySeq方法的对象在pattern match时也有很好的应用场景。

比如这段代码:

1
2
3
object Square {
def unapply(z: Double): Option[Double] = Some(math.sqrt(z))
}

我们定义了一个unapply方法,用来计算平方根。 我们可以像调用普通方法一样的调用它:

1
2
val number: Double = 36.0
Square.unapply(number)

这样会得到36的平方根:6。实际上返回值是Some(6)。

上面的方式是对unapply的浪费,unapply真正的好处是这样的:

1
2
3
4
5
val number: Double = 36.0
number match {
case Square(n) => println(s"square root of $number is $n")
case _ => println("nothing matched")
}

这样我们无需显式调用unapply方法,而把是它用在pattern match中,让编译器替我们调用它。

当我们写下这段pattern match的代码时,编译器其实替我们做了好几件事:

  1. 调用unapply,传入number
  2. 接收返回值并判断返回值是None,还是Some
  3. 如果是Some,则将其解开,并将其中的值赋值给n(就是case Square(n)中的n)

这段代码反编译出来是这个样子的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  double number = 36.0D;
double d1 = number;
Option localOption = Square..MODULE$.unapply(d1);
//调用unapply,传入number
BoxedUnit localBoxedUnit;
if (localOption.isEmpty()) {//判断返回值是None
Predef..MODULE$.println("nothing matched");
localBoxedUnit = BoxedUnit.UNIT;
}
else {//判断返回值是Some
double n = BoxesRunTime.unboxToDouble(localOption.get());
//将Some解开,并将其中的值赋值给n
Predef..MODULE$.println(new StringContext(Predef..MODULE$.wrapRefArray((Object[]) new String[] {
"square root of ", " is ", ""
}) ).s(Predef..MODULE$.genericWrapArray(new Object[] {
BoxesRunTime.boxToDouble(number), BoxesRunTime.boxToDouble(n)
})));
localBoxedUnit = BoxedUnit.UNIT;
}

如果没有unapply方法和pattern match语法之间的这种结合,我们自己写代码要写成什么样子呢?

或许会比上面反编译的代码简单一些,但是显式地调用开平方的方法,用if else来判断Option,以及将真正的返回值从Option里面解出来这三件事是免不掉的。

unapplySeq和unapply的作用很是类似,例如这样:

1
2
3
4
5
6
object Names {
def unapplySeq(str: String): Option[Seq[String]] = {
if (str.contains(",")) Some(str.split(","))
else None
}
}

我们定义一个unapplySeq方法,用逗号作为分隔符来把字符串拆开。

然后我们可以这样应用它:

1
2
3
4
5
6
7
8
val namesString = "xiao ming,xiao hong,tom"
namesString match {
case Names(first, second, third) => {
println("the string contains three people's names")
println(s"$first $second $third")
}
case _ => println("nothing matched")
}

与上面的例子很是类似,不过编译器在这里替我们做的事情更多了:

  1. 调用unapplySeq,传入namesString
  2. 接收返回值并判断返回值是None,还是Some
  3. 如果是Some,则将其解开
  4. 判断解开之后得到的sequence中的元素的个数是否是三个
  5. 如果是三个,则把三个元素分别取出,赋值给first,second和third

如果没有unapplySeq方法和pattern match语法之间的这种结合,我们自己写代码来做这五件事会显得很是繁琐。

Desugar Scala(15) -- unapply和unapplySeq方法的更多相关文章

  1. Scala - 语言专家 - Desugar Scala code

    https://mp.weixin.qq.com/s/zwrG1MfUzXwtik7jotpQsA   介绍Intellij IDEA中的一个去除Scala语法糖的功能.     ​​   1. 去除 ...

  2. Desugar Scala(16) -- Lower Bound

    欢迎关注我的新博客地址:http://cuipengfei.me/ Lower bound,不知道这个词的确切中文翻译是怎样的.我们直接看例子吧. 1 2 3 class Pair[T](val fi ...

  3. scala集合上常用的方法

    sacala 关于集合常用的操作 map1.映射:对集合中的每一个元素进行执行某一项操作2.返回值类型,正常情况不变,原来集合是什么类型,就返回什么类型3.元素类型,根据我们函数的返回值类型 val ...

  4. struts2.3.15.3中动态方法调用默认是关闭的

    初学ssh,用的struts2.3.15.3,使用了如下表单: <form action="/spring3/index/login.action" method=" ...

  5. 15个HTML元素方法!

    首先让我们来讨论一下 HTML 与 DOM 之间的区别. 显然,普通的 <table> 元素就是一段 HTML 代码,它可以应用在任何一个以 .html 为扩展名的文件中.元素自带一系列特 ...

  6. Desugar Scala(17) -- Option和for,以及脑子里发生的事情

    欢迎关注我的新博客地址:http://cuipengfei.me/blog/2014/08/30/options-for/ Scala里的forkeyword是个非常有趣的东西. 能够用来把多层嵌套f ...

  7. scala学习手记34 - trait方法的延迟绑定

    trait的方法的延迟绑定就是先混入的trait的方法会后调用.这一点从上一节的实例中也可以看出来. 下面再来看一个类似的例子: abstract class Writer { def write(m ...

  8. 深入15个HTML元素方法,你见过吗?

    虽然现代化的 web 开发更多地依赖各种 MVC 框架,但开发者仍需要熟练掌握 HTML 与 DOM 方面的基础知识.不过,即使是有着多年经验的前端开发者,也会遇到一些不明所以的情况.本文首先将为初学 ...

  9. Spark Scala 读取GBK文件的方法

    1. 在生产环境下,很多文件是GBK编码格式的,而SPARK 常用的textFile方法默认是写死了读UTF-8格式的文件,其他格式文件会显示乱码 用如下代码实现读取GBK文件的方法 import o ...

随机推荐

  1. 从头认识java-13.11 对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题?

    这一章节我们继续类型擦除的话题,我们将通过对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题? 1.数组 package com.ray.ch13; public class Test { pub ...

  2. Cocos2d-x 处理双击事件的两种方法

    在cocos2d-x的开发过程中有些时候也是需要用到双击的事件处理,那么由于在cocos2d-x中没有实现对双击的事件的处理,那么我们就需要自己用代码实现. 下面介绍两种方式实现双击事件的处理. (一 ...

  3. java程序设计题库

    选择题 答题要求:单选题,每题只有一个正确答案,选择正确给分,不正确不给分. 1. 下面(   A    )数据类型可用于main()方法中传递的参数 A.String   B.Integer   C ...

  4. 页面刷新 vuex 数据重新被初始化

    1.原因 vuex里用来存储的也只是一个全局变量,当页面刷新,该全局变量自然不存在了. 2.解决 使用localStorage存储一份 (1)storage.js /** * vuex localSt ...

  5. css实现图片水平垂直居中

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. Java Source Attacher 1.2 发布

    Java Source Attacher 1.2 是一款自动帮你附加源代码的Eclipse插件,相信很多Java Coder都有过手动附加源代码的经历,去网上搜索,然后下载下来,最后附加上,很麻烦,而 ...

  7. C-常用构造哈希函数

    1.定址法(比如0-100岁的人数统计, 可以按年龄作为散列地址, 1980年后每年出生人数的统计, 可以把"年限 - 1980"作为散列地址) 2.取余法 3.数字分析法(比如一 ...

  8. 开发基于CXF的 RESTful WebService web 项目 webservice发布

    配置步骤 开发基于CXF的 RESTful WebService 1.创建Web项目并导入CXF的jar 2.在Web.xml中配置 CXFServlet <servlet> <se ...

  9. Cookie技术

    u  常用的API 创建Cookie对象 Cookie(String name, String value)    ->以指定数据创建Cookie对象 设置Cookie对象 void setMa ...

  10. Linux命令-压缩解压命令:bzip2、bunzip2

    bzip2是gzip的升级版 bzip2 [选项] 源文件名(压缩前) -k 保留源文件,(区别gzip不支持保留源文件) bunzip2 [选项] 源文件名(压缩后) 压缩文件: bzip2 -k ...