Desugar Scala(15) -- unapply和unapplySeq方法
2017-04-20 12:56
351 查看
欢迎关注我的新博客地址:http://cuipengfei.me/
实在想不到什么动词能够当做脱衣服来讲了。所以从如今開始这系列博文就叫做Desugar Scala了。除非哪天才思泉涌,又想到了新词:)
開始正文。
名字叫做unapply和unapplySeq的方法在Scala里也是有特殊含义的。
我们前面说过case class在做pattern match时非常好用,而除case class之外,有unapply或unapplySeq方法的对象在pattern match时也有非常好的应用场景。
比方这段代码:
我们定义了一个unapply方法,用来计算平方根。
我们能够像调用普通方法一样的调用它:
这样会得到36的平方根:6。实际上返回值是Some(6)。
上面的方式是对unapply的浪费。unapply真正的优点是这种:
这样我们无需显式调用unapply方法,而把是它用在pattern match中。让编译器替我们调用它。
当我们写下这段pattern match的代码时,编译器事实上替我们做了好几件事:
调用unapply,传入number
接收返回值并推断返回值是None,还是Some
假设是Some,则将其解开,并将当中的值赋值给n(就是case Square(n)中的n)
这段代码反编译出来是这个样子的:
假设没有unapply方法和pattern match语法之间的这样的结合,我们自己写代码要写成什么样子呢?
也许会比上面反编译的代码简单一些,可是显式地调用开平方的方法。用if else来推断Option,以及将真正的返回值从Option里面解出来这三件事是免不掉的。
unapplySeq和unapply的作用非常是类似,比如这样:
我们定义一个unapplySeq方法,用逗号作为分隔符来把字符串拆开。
然后我们能够这样应用它:
与上面的样例非常是类似,只是编译器在这里替我们做的事情很多其它了:
调用unapplySeq,传入namesString
接收返回值并推断返回值是None,还是Some
假设是Some,则将其解开
推断解开之后得到的sequence中的元素的个数是否是三个
假设是三个,则把三个元素分别取出,赋值给first,second和third
假设没有unapplySeq方法和pattern match语法之间的这样的结合,我们自己写代码来做这五件事会显得非常是繁琐。
实在想不到什么动词能够当做脱衣服来讲了。所以从如今開始这系列博文就叫做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)) } |
我们能够像调用普通方法一样的调用它:
1 2 | val number: Double = 36.0 Square.unapply(number) |
上面的方式是对unapply的浪费。unapply真正的优点是这种:
1 2 34 | val number: Double = 36.0 number match { case Square(n) => println(s"square root of $number is $n") case _ => println("nothing matched") } |
当我们写下这段pattern match的代码时,编译器事实上替我们做了好几件事:
调用unapply,传入number
接收返回值并推断返回值是None,还是Some
假设是Some,则将其解开,并将当中的值赋值给n(就是case Square(n)中的n)
这段代码反编译出来是这个样子的:
1 2 34 | 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; } |
也许会比上面反编译的代码简单一些,可是显式地调用开平方的方法。用if else来推断Option,以及将真正的返回值从Option里面解出来这三件事是免不掉的。
unapplySeq和unapply的作用非常是类似,比如这样:
1 2 34 | object Names { def unapplySeq(str: String): Option[Seq[String]] = { if (str.contains(",")) Some(str.split(",")) else None } } |
然后我们能够这样应用它:
1 2 34 | 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") } |
调用unapplySeq,传入namesString
接收返回值并推断返回值是None,还是Some
假设是Some,则将其解开
推断解开之后得到的sequence中的元素的个数是否是三个
假设是三个,则把三个元素分别取出,赋值给first,second和third
假设没有unapplySeq方法和pattern match语法之间的这样的结合,我们自己写代码来做这五件事会显得非常是繁琐。
相关文章推荐
- Desugar Scala(15) -- unapply和unapplySeq方法
- Desugar Scala(15) -- unapply和unapplySeq方法
- Scala的apply()、unapply()、unapplySeq()方法
- scala中的apply方法与unapply方法
- Scala apply() unapply() update() 方法
- scala 的apply,update,unapply方法
- scala 奇淫巧技 - 3.apply unapply unapplySeq 语法糖
- scala中的apply方法与unapply方法
- Scala 中的 apply 和 update 方法
- scala入门-08 apply方法和单例对象的使用
- apply方法 Scala学习笔记-面向对象篇
- scala的 apply方法
- scala中的apply和unapply
- scala基础15-抽象(类、字段、方法)
- Scala课堂-2-基础(续)-apply方法、单例对象、模式匹配、样本类
- scala中的apply和update方法
- Scala 中apply方法的用法~(转)
- 一步步学spark之一scala的apply方法2.3
- Scala学习笔记-apply方法
- scala 学习笔记(04) OOP(上)主从构造器/私有属性/伴生对象(单例静态类)/apply方法/嵌套类