定义

隐式参数

隐式参数指在函数或者方法中,定义一个用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】什么是隐式转换?它又能用来干嘛?该怎么用的更多相关文章

  1. Scala 中的隐式转换和隐式参数

    隐式定义是指编译器为了修正类型错误而允许插入到程序中的定义. 举例: 正常情况下"120"/12显然会报错,因为 String 类并没有实现 / 这个方法,我们无法去决定 Stri ...

  2. scala高级性质-隐式转换 -02

    今天我们来介绍scala的高级特性,上次已经介绍过他的一个特性:高阶函数,这次是隐式转换 1.隐式转换的例子 read的例子 解析:发现这个file没有read的方法,然后就开始在开始在这个上下文里面 ...

  3. Scala学习笔记--隐式转换

    隐式转换的规则:1.无歧义规则:隐式转换唯有不存在其他可插入转换的前提下才能插入  若编译器有两种方法修正x+y 如convert1(x)+y,convert2(x)+y,会报错2.单一调用规则:只尝 ...

  4. Scala入门系列(十二):隐式转换

    引言 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象.通过这些功能可以实现非常强大而且特殊的功 ...

  5. Scala 隐式转换及应用

    什么是隐式转换 我们经常引入第三方库,但当我们想要扩展新功能的时候通常是很不方便的,因为我们不能直接修改其代码.scala提供了隐式转换机制和隐式参数帮我们解决诸如这样的问题. Scala中的隐式转换 ...

  6. Scala隐式转换

    package big.data.analyse.scala import java.io.File import scala.io.Source /** * 隐式转换 * Created by zh ...

  7. Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、

    1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...

  8. Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)

    object func { def main(args:Array[String]):Unit={ //函数赋值给变量时, 必须在函数后面加上空格和下划线. def sayHello(name: St ...

  9. Scala学习之路 (八)Scala的隐式转换和隐式参数

    一.概念 Scala 2.10引入了一种叫做隐式类的新特性.隐式类指的是用implicit关键字修饰的类.在对应的作用域内,带有这个关键字的类的主构造函数可用于隐式转换. 隐式转换和隐式参数是Scal ...

  10. Scala隐式转换和隐式参数

    隐式转换 Scala提供的隐式转换和隐式参数功能,是非常有特色的功能.是Java等编程语言所没有的功能.它可以允许你手动指定,将某种类型的对象转换成其他类型的对象或者是给一个类增加方法.通过这些功能, ...

随机推荐

  1. 9. 弹出键盘挡住input

    1.) react 中 <input className="inp3" placeholder="密码" type="password" ...

  2. [PHP][linux] 命令行脚本接收传入参数的

    第一种 :用{ $argv }接受参数 第二种 : getopt() 第三种:

  3. layui table渲染和数据处理

    最近在用layui开发管理系统,果然是"累"ui 实现功能:将之前选择的选项勾选,渲染备注信息(原数据为空的列) <table class="layui-hide& ...

  4. pytorch中tensor张量的创建

    import torch import numpy as np print(torch.tensor([1,2,3])) print(torch.tensor(np.arange(15).reshap ...

  5. 如何用TensorFlow实现线性回归

    环境Anaconda 废话不多说,关键看代码 import tensorflow as tf import os os.environ['TF_CPP_MIN_LOG_LEVEL']='2' tf.a ...

  6. PHP 使用try catch,捕获异常

    <?php     header('Content-type:text/html;charset=utf-8');    $a = 1;    $b = 2;    try {        / ...

  7. 2019-2020-1 20199329《Linux内核原理与分析》第一周作业

    Linux学习随笔 Linux 是一个操作系统,我们的 Linux 主要是系统调用和内核那两层. UNIX前身是Multics,但 UNIX 的商业版本非常昂贵,于是Linus Torvalds(Li ...

  8. 汇编 之 win10 下安装dosbox 和 MASM

    所需工具链接: 链接:https://pan.baidu.com/s/1nenMsSdgEkeRKc6wh9DQRA 提取码:1r89 只需要以下两个工具 安装dosbox 和MASM步骤 (1)解压 ...

  9. Mina Basics 02-基础

    基础 在第1章中,我们简要介绍了Apache MINA.在本章中,我们将了解客户端/服务器体系结构以及有关基于MINA的服务器和客户端的详细信息. 我们还将基于TCP和UDP公开一些非常简单的服务器和 ...

  10. zabbix3.x.x升级教程

    1:停掉正在运行的zabbix服务,确保没有新数据写入数据库. /etc/init.d/zabbix_server stop 2:备份原zabbix的数据库数据,以及相关文件. mysqldump - ...