【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等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法.通过这些功能, ...
随机推荐
- three.js obj转js的详细步骤 convert_obj_three.py的用法
three.js是最近非常流行的一个前端webgl库. js格式的模型文件是three.js中可以直接加载的文件.使用THREE.JSONLoader()直接加载,而不需要引用其它的loader插件. ...
- L6循环神经网络
循环神经网络 本节介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型.我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符.循环神经网络引入一个隐藏变量HHH,用HtH_{t}H ...
- c++全排列
一.概念 从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列.当m=n时所有的排列情况叫全排列.如果这组数有n个,那么全排列数为n!个. 比如a ...
- C - League of Leesins
乱搞一发,,竟然过了!!! 题目大意:输入一个整数n,然后n-2行,每一行3个数字,表示一个数组中连续的3个数字,然后将这3个数字的顺序打乱,然后再将这个n-2行打乱,要求还原数组. 题解:先找到前3 ...
- SQL语句加锁分析
背景 MySQL中SQL加锁的情况十分复杂,不同隔离级别.不同索引类型.索引是否命中的SQL加锁各不相同. 然而在分析死锁过程当中,熟知各种情况的SQL加锁是分析死锁的关键,因此需要将MySQL的各种 ...
- 如何优雅的维护 K8S Worker 节点
前言 正常维护工作节点的流程 当我们要进行 K8S 节点维护时往往需要执行 kubectl drain, 等待节点上的 Pod 被驱逐后再进行维护动作. 命令行如下: kubectl drain NO ...
- fedora 21下Virtual Box安装Windows XP SP3
Installing Virtual Box and Windows XP SP3 during Fedora 21 The first step:Download and Install Virtu ...
- AWS访问慢的原因分析及解决方案
中国区的用户在访问海外AWS服务器的时候会遇到访问很慢的情况,那如何快速访问海外AWS服务器,今天和大家一起聊一下这个话题. 首先,为什么中国的用户访问海外AWS会变慢? 我总结来下大概有以下几方面的 ...
- 杭电的题,输出格式卡的很严。HDU 1716 排列2
题很简单,一开始写代码,是用整数的格式写的,怎么跑都不对,就以为算法错了,去看大佬们的算法STL全排列:next_permutation(); 又双叒叕写了好几遍,PE了将近次,直到跑了大佬代码发现, ...
- STL训练 HDU - 1716 Ray又对数字的列产生了兴趣:
HDU - 1716 Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数. Input 每组数据占一行,代表四张卡片上的数字(0&l ...