【Scala】什么是隐式转换?它又能用来干嘛?该怎么用
定义
隐式参数
隐式参数指在函数或者方法中,定义一个用implicit修饰的参数,此时Scala会尝试找到一个指定类型的,用implicit修饰的参数,即隐式值,并注入参数。
Scala会在两个范围进行查找:
1.当前作用域内可见的val或var定义的隐式变量
2.隐式参数类型的伴生对象内的隐式值
隐式转换
当Scala编译器进行类型匹配时,如果找不到合适的候选,那么隐式转化提供了另外一种途径来告诉编译器如何将当前的类型转换成预期类型。
其中最核心的就是自己定义隐式转换方法(implicit conversion function),Scala会根据隐式转换方法的签名,在程序中使用到隐式转换方法接收的参数类型定义的对象时,会自动将其传入隐式转换方法,转换为另外一种类型的对象并返回。所有的隐式值和隐式方法都必须放到object中。
什么时候要进行隐式转换?
1.当对象调用类中不存早的方法或成员时,编译器会自动将对象进行隐式转换
2.当方法中的参数类型与目标类型不一致时
隐式转换的限制:
1.implicit关键字只能用来修饰方法、变量(参数)
2.隐式转换的方法在当前范围内才有效,如果隐式转换不在当前范围内定义(比如定义在了另一个类中或者包含在某个对象中),就必须通过import语句导入
隐式转换使用方式:
1.将方法或变量标记为implicit
2.将方法的参数列表标记为implicit
3.将类标记为implicit
隐式值:给方法提供参数
//先定义一个普通的方法
scala> def m1(name:String) = println(name)
m1: (name: String)Unit
//给定匹配的参数类型不会报错
scala> m1("LeiJun")
LeiJun
//如果给了不匹配的参数类型就会报错
scala> m1(2)
<console>:13: error: type mismatch;
found : Int(2)
required: String
m1(2)
^
//或者不给参数也会报错
scala> m1
<console>:13: error: missing argument list for method m1
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `m1 _` or `m1(_)` instead of `m1`.
m1
^
//现在重新定义一个方法,参数用implicit修饰
scala> def m2(implicit name:String) = println(name)
m2: (implicit name: String)Unit
//只输出m2依然会报错,不过和之前已经不一样了
//显示的是“找不到参数name: String的隐式值”
scala> m2
<console>:13: error: could not find implicit value for parameter name: String
m2
^
//那就定义隐式值
scala> implicit val a:String = "money"
a: String = money
//只输出m2发现发生了隐式转换
scala> m2
money
scala> m2("123")
123
//如果再定义一个同类型的隐式值
scala> implicit val b:String = "love"
b: String = love
//就会报错,“爱情面包不可兼得”
scala> m2
<console>:15: error: ambiguous implicit values:
both value a of type => String
and value b of type => String
match expected type String
m2
^
隐式视图
将Int和Double类型转换为String
scala> def m1(name:String) = println(name)
m1: (name: String)Unit
//定义一个将Int类型转换为String的隐式转换方法
scala> implicit def Int2String(x:Int) = x.toString
warning: there was one feature warning; re-run with -feature for details
Int2String: (x: Int)String
scala> m1(123)
123
//定义一个将Double类型转换为String的隐式转换方法
scala> implicit def Double2String(x:Double) = x.toString
warning: there was one feature warning; re-run with -feature for details
Double2String: (x: Double)String
scala> m1(3.14)
3.14
狗狗学技能(使用别的类中的方法)
狗狗学习导盲技能
class Learn {
def learnMore(skills:String) = println(skills)
}
// implicit 隐式转换
object Teaching{
//定义隐式转换的方法 让一个类可以调用另一个类
implicit def dogLearning(dog: Dog) = new Learn
}
class Dog{
}
object FinalDog{
def main(args: Array[String]): Unit = {
//创建Dog对象
val dog = new Dog
//手动导入隐式转换方法
import cn.itcast.scala.implicit_demo.Teaching.dogLearning
//Dog自己的类中并没有learnMore方法,通过隐式转换就可以直接调用Learn类中的方法
dog.learnMore("导盲")
}
}
使用规则
1. Scala一般指考虑处于作用域之内的隐式转换,不过可以通过import调用其他类中的方法,比如上面用到的import cn.itcast.scala.implicit_demo.Teaching.dogLearning。
2. 无歧义规则。隐式转换必须在不存在其他可插入转换的前提下才能插入。比如:
scala> implicit def String2Int(s:String) = s.toInt
warning: there was one feature warning; re-run with -feature for details
String2Int: (s: String)Int
scala> implicit def String2Double(s:String) = s.toDouble
<console>:18: error: type mismatch;
found : s.type (with underlying type String)
required: ?{def toDouble: ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method augmentString in object Predef of type (x: String)scala.collection.immutable.StringOps
and method String2Int of type (s: String)Int
are possible conversion functions from s.type to ?{def toDouble: ?}
implicit def String2Double(s:String) = s.toDouble
^
<console>:18: error: value toDouble is not a member of String
Note: implicit method String2Double is not applicable here because it comes after the application point and it lacks an explicit result type
implicit def String2Double(s:String) = s.toDouble
^
上面两个都想通过隐式转换同时将String类型转换为Int和Double,如果要进行转换运算时,就会产生歧义,scala会不明白到底是要将输入的String类型参数转换为Int类型还是Double类型
3. 单一调用原则。scala只会尝试一个隐式操作,不会对某个变量执行多次隐式转换。
比如说,现在想将输入的String类型参数转换为Int,然后定义了一个将String类型隐式转换为Int的方法
implicit def String2Int(s:String) = s.toInt,结果又想将输入的Int参数转换为Double类型,又将Double类型转换为String类型,编译器将只会尝试最初定义的隐式转换方法
4. 显示操作现行原则。编译器发现代码类型并没有发生错误时,不会进行隐式转换操作。
5.最好将自己定义的隐式转换方法放到一个类中,使用时通过import,这样方便管理,复用性也比较强
【Scala】什么是隐式转换?它又能用来干嘛?该怎么用的更多相关文章
- Scala 中的隐式转换和隐式参数
隐式定义是指编译器为了修正类型错误而允许插入到程序中的定义. 举例: 正常情况下"120"/12显然会报错,因为 String 类并没有实现 / 这个方法,我们无法去决定 Stri ...
- scala高级性质-隐式转换 -02
今天我们来介绍scala的高级特性,上次已经介绍过他的一个特性:高阶函数,这次是隐式转换 1.隐式转换的例子 read的例子 解析:发现这个file没有read的方法,然后就开始在开始在这个上下文里面 ...
- Scala学习笔记--隐式转换
隐式转换的规则:1.无歧义规则:隐式转换唯有不存在其他可插入转换的前提下才能插入 若编译器有两种方法修正x+y 如convert1(x)+y,convert2(x)+y,会报错2.单一调用规则:只尝 ...
- Scala入门系列(十二):隐式转换
引言 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象.通过这些功能可以实现非常强大而且特殊的功 ...
- Scala 隐式转换及应用
什么是隐式转换 我们经常引入第三方库,但当我们想要扩展新功能的时候通常是很不方便的,因为我们不能直接修改其代码.scala提供了隐式转换机制和隐式参数帮我们解决诸如这样的问题. Scala中的隐式转换 ...
- Scala隐式转换
package big.data.analyse.scala import java.io.File import scala.io.Source /** * 隐式转换 * Created by zh ...
- Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、
1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...
- Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)
object func { def main(args:Array[String]):Unit={ //函数赋值给变量时, 必须在函数后面加上空格和下划线. def sayHello(name: St ...
- Scala学习之路 (八)Scala的隐式转换和隐式参数
一.概念 Scala 2.10引入了一种叫做隐式类的新特性.隐式类指的是用implicit关键字修饰的类.在对应的作用域内,带有这个关键字的类的主构造函数可用于隐式转换. 隐式转换和隐式参数是Scal ...
- Scala隐式转换和隐式参数
隐式转换 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法.通过这些功能, ...
随机推荐
- 远程登录redis
没想到吧,我居然已经摸到了redis. 远程登录redis redis-cli -h 127.0.0.1 -p 6379 ip地址和端口记得换成自己的
- vue2.x学习笔记(八)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12577433.html. 列表渲染 vue提供了一个[v-for]指令用于列表渲染(循环). 用[v-for]指令 ...
- SQLI-LABS学习笔记(一)
逼话少说,如有错误,烦请指出,谢谢. 第一关 提示传个id的参数 后面跟个单引号 http://10.2.10.31/sqli/Less-1/?id=1’ 发现报错,这里看到是已经闭合了 You ha ...
- 二, 连接Oracle 二
一,sqlplus操作 文件操作命令 1.start和@ 说明: 运行sql脚本 案例: sql>@ home/a.sql或是sql>start home/a.sql 2.edit 说明: ...
- Inno Setup 大师 Tlama
https://stackoverflow.com/users/960757/tlama
- 对 ThreadLocal 的了解(一)
Threadlocal ThreadLocal 在我个人理解范围内,主要作用是在同一个线程里面,去共享某个数据给这个线程在不同的阶段去使用. 本次使用范围 在集成 pageOffice 在线 word ...
- 谷歌提高Google Assistant中Voice Match的准确性
谷歌正在提高 Google Assistant 中 Voice Match 的准确性,使其变得更加完善.谷歌表示一旦用户在 Google Assistant 中启用 Voice Match 功能,那么 ...
- 记django从1.11.7升级到2.0.1
第一步:升级django之后记录下django等其他相关依赖包的版本号. 在terminal中输入 pip freeze, 获取所有包的版本号.为了在升级不成功后可以回到低版本. 第二步:卸载再重装d ...
- 美国在线CEO:雅虎被Verizon收购或导致裁员
北京时间9月13日消息,据外媒报道,AOL首席执行官蒂姆·阿姆斯特朗(Tim Armstrong)称,雅虎.AOL和Verizon整合业务,将导致"部分工作岗位的变化". 阿姆斯特 ...
- 微信Webapp开发的各种变态路由需求及解决办法!
前言 最近在使用BUI Webapp开发的一个小商城项目在微信上遇到一些坑及变态需求, 层层深入, 整理一下给后来人参考. 一定有你还不知道的! 调试缓存 问题描述: 微信打开的web页面默认是会缓存 ...