Scala学习笔记--隐式转换
隐式转换的规则:
1.无歧义规则:隐式转换唯有不存在其他可插入转换的前提下才能插入
若编译器有两种方法修正x+y 如convert1(x)+y,convert2(x)+y,会报错
2.单一调用规则:只尝试一个隐式操作,编译器不会把x+y重写成convert1(convert2(x))+y
3.显式调用规则:若编写的代码没有错误,则不会尝试任何隐式操作
4.命名隐式转换:隐式转换可以任意命名
def main(args:Array[String]):Unit={
implicit def doubleToInt(x:Double) = x.toInt
val i:Int = 3.5;
println(i) //编译器在语境中看到了Double,但它需要的是Int。
//如果没有第一行 implicit def doubleToInt(x:Double) = x.toInt 编译器会报错
//###但是在放弃之前,它搜索了从Double 到Int的隐式转换。
//在本例中,它发现了一个doubleToInt,编译器于是自动插入了doubleToInt调用
//代码实际变成了val i:Int = doubleToInt(3.5)
}
隐式参数
class PreferredPrompt(val preference:String)
class PreferredDrink(val preference:String)
object Greeter{
def greet(name: String)(implicit prompt:PreferredPrompt,drink:PreferredDrink){ //参数列表被标记为implicit,也就是说它可以被隐式提供
println("Welcome," + name + ". The system is ready.");
println("喝点什么?")
println(drink.preference );
println(prompt.preference); }
}
object Test3{
def main(args:Array[String]):Unit={ //为了让编译器隐式提供参数,必须先定义期望类型的变量
implicit val p1 = new PreferredPrompt("Lin>")
implicit val p2 = new PreferredDrink("tea")
//p1本身也被标记为implicit 否则不能用来补充下面确实的参数列表
Greeter.greet("JJ")
}
/*//不使用隐式参数的情况
def main(args:Array[String]):Unit={
val p1 = new PreferredPrompt("Lin")
Greeter.greet("JJ")(p1)
}
*/
}
结果:
Welcome,JJ. The system is ready.
喝点什么?
tea
Lin>
隐式转换
隐式的函数参数也可以被用作隐式转换。为了明白它的重要性,首先考虑如下泛型函数:
def smaller[T](a:T,b:T)={
if(a<b) a else b
}
这实际上行不通,因为它并不知道a和b数以一个带有<操作符的类型。
我们可以提供一个转换函数来达到目的:
def smaller[T](a:T,b:T)(implicit order: T=>Ordered(T))={
if(order(a)<b) a else b
}
由于Ordered[T]特质有一个接受T作为参数的<操作符,因此这个版本是正确的。
注意order是一个带有单个参数的函数,被打上了implicit标签,并且有一个以单个标识符出现的名称。
因此,它不仅是隐式参数,而且是隐式转换。因此,在函数体中可以略去对order的显示调用
def smaller[T](a:T,b:T)(implicit order: T=>ordered(T))={
if(a<b) a else b
}
另一个例子。
object Test4{
def main(args:Array[String]):Unit={
val l1 = List(24,6,7,34,5,14,23)
println(maxListUpBound(l1))
}
def maxListUpBound[T](elements:List[T])(implicit orderer:T=>Ordered[T]):T={//这里用到了隐式转换
// def maxListPoorStyle[T](elements:List[T])(implicit orderer:(T,T)=>Boolean):T={ //太过平凡
// def maxListUpBound[T<:Ordered[T]](elements:List[T]):T={ //不可行,因为T未必是Ordered[T]的子类
// def maxListUpBound(elements:List[Int]):Int={
elements match{
case List()=> throw new IllegalArgumentException("empty list!")
case List(x)=>x
case x::rest =>
val maxRest = maxListUpBound(rest)(orderer)
if(orderer(x) > maxRest) x;
else maxRest
}
}
} /*隐式参数的样式规则。最好对隐式参数的类型使用自定义命名的类型,例如不用String 而用
PreferredPrompt 和PreferredDrink
反例
def maxListPoorStyle[T](elements:List[T])(implicit orderer:(T,T)=>Boolean):T
为了使用函数的这个版本,调用这必须提供类型为(T,T)=>Boolean的orderer参数
这种类型过于平凡,包含了任何两个T对象产生的Boolean函数
*/
视界
def maxListUpBound[T<%Ordered[T]](elements:List[T]):T={
elements match{
case List()=> throw new IllegalArgumentException("empty list!")
case List(x)=>x
case x::rest =>
val maxRest = maxListUpBound(rest)
if(x > maxRest) x;
else maxRest
} }
可以认为 T<%Ordered[T] 是在说, 任何的T都好,只要能把T当做Orderer[T]即可
例如 尽管Int不是Ordered[Int]的子类型,但是只要Int到Ordered[Int]的隐式转换可用
仍然可以把List[T]传给maxListUpBound
Scala学习笔记--隐式转换的更多相关文章
- Scala 中的隐式转换和隐式参数
隐式定义是指编译器为了修正类型错误而允许插入到程序中的定义. 举例: 正常情况下"120"/12显然会报错,因为 String 类并没有实现 / 这个方法,我们无法去决定 Stri ...
- js学习日记-隐式转换相关的坑及知识
隐式转换比较是js中绕不过去的坎,就算有几年经验的工程师也很有可能对这块知识不够熟悉.就算你知道使用===比较从而避免踩坑,但是团队其它成员不一定知道有这样或那样的坑,有后端语言经验的人常常会形成一个 ...
- scala高级性质-隐式转换 -02
今天我们来介绍scala的高级特性,上次已经介绍过他的一个特性:高阶函数,这次是隐式转换 1.隐式转换的例子 read的例子 解析:发现这个file没有read的方法,然后就开始在开始在这个上下文里面 ...
- C++学习笔记-隐式成员函数
通过一个例子来复习C++操作符重载及隐式成员函数.MyString类模仿标准string类,简单的实现了构造一个字符串.字符串比较.取单个字符等功能.如下: #ifndef MYSTRING_H_ # ...
- Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、
1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...
- Scala学习之路 (八)Scala的隐式转换和隐式参数
一.概念 Scala 2.10引入了一种叫做隐式类的新特性.隐式类指的是用implicit关键字修饰的类.在对应的作用域内,带有这个关键字的类的主构造函数可用于隐式转换. 隐式转换和隐式参数是Scal ...
- Scala 学习之路(十三)—— 隐式转换和隐式参数
一.隐式转换 1.1 使用隐式转换 隐式转换指的是以implicit关键字声明带有单个参数的转换函数,它将值从一种类型转换为另一种类型,以便使用之前类型所没有的功能.示例如下: // 普通人 clas ...
- Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)
object func { def main(args:Array[String]):Unit={ //函数赋值给变量时, 必须在函数后面加上空格和下划线. def sayHello(name: St ...
- Scala入门系列(十二):隐式转换
引言 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象.通过这些功能可以实现非常强大而且特殊的功 ...
随机推荐
- Anisotropic gauss filter
最近一直在做版面分析,其中文本行检测方面,许多文章涉及到了Anigauss也就是各向异性高斯滤波. 顾名思义,简单的理解就是参数不同的二维高斯滤波. 在文章Fast Anisotropic Gauss ...
- 最近写的页面,含有大量的ajax
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib ur ...
- 从现在开始使用nodejs开发的几点答疑
1.为什么要开始用nodejs, 而不是php 理由有三点: 因为我是前端程序员出身,nodejs都是用javascript写的,这样相当于前端和后端都使用javascript,开发更加有效率.当然很 ...
- My advice to young people - Donald Knuth [video]
http://www.youtube.com/watch?v=75Ju0eM5T2c I took a note of what knuth said in the video. 1. Don't d ...
- SeekBar.OnSeekBarChangeListener解析
public static interface SeekBar.OnSeekBarChangeListener android.widget.SeekBar.OnSeekBarChangeListen ...
- (step5.1.6)hdu 1272(小希的迷宫——并查集)
题目大意:输入一系列的点,判断这些点组成的图符不符合小希的思路(无环.连通) 解题思路: 1)如果两个节点的根节点相同,那么在这两个节点之间添加1条边以后,这个图肯定有环路. 2)孤立节点:被使用过& ...
- Android——ViewPager多页面滑动切换以及动画效果
一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式,白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了, ...
- 第24讲 UI_布局 之帧布局 表格布局 绝对布局
第24讲 UI_布局 之帧布局 表格布局 绝对布局 3. FrameLayout(帧布局) 帧布局是从屏幕的左上角(0,0)坐标开始布局,多个组件层叠排序,后一个组件总会将前一个组件所覆盖,除非最后一 ...
- tab切换jquery代码
http://immmmm.com/jquery-tab-switch-code-improved.html html <div id="sidebar-tab"> ...
- 真实经纬度(gps)转成百度坐标的js方法
转:http://www.360doc.com/content/16/0320/14/18636294_543805051.shtml 结果图: <!DOCTYPE html> <h ...