一,隐式转换函数

1, 格式,

implicit def 函数名(参数):返回值类型={
//函数体
//返回值
}

2,例子:

//导入对应的规则类,以免出现警告
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
//定义将Int类型的值转换为Float的函数
scala> implicit def int2float(x:Int): Float = x.toFloat
int2float: (x: Int)Float scala> val x:Float = 2
x: Float = 2.0
scala>

3,注意事项:

1) 隐式转换函数的函数名可以是任意的,与函数名称无关,只与函数签名(函数参数和返回值类型)有关。

2)如果当前作用域中存在函数签名相同但函数名称不同的两个隐式转换函数,则在进行隐式转换时会报错。

//函数一
scala> implicit def int2float2(x: Float): Int = x.toInt
int2float2: (x: Float)Int
//函数二
scala> implicit def int2float(x: Float): Int = x.toInt
int2float: (x: Float)Int
//调用,报错
scala> val x:Int = 2.55f
<console>:14: error: type mismatch;
found : Float(2.55)
required: Int
Note that implicit conversions are not applicable because they are ambiguous:
both method int2float2 of type (x: Float)Int
and method int2float of type (x: Float)Int
are possible conversion functions from Float(2.55) to Int
val x:Int = 2.55f
^

二,隐式类与隐式对象

    1,隐式类:通过在类名前使用 implicit 关键字定义

         1)格式:

implicit class 类名(参数){
//类主体
}

例子:string中没有bark方法,通过隐式转换,调用对应的方法转换

scala> implicit class Dog(val name: String){
| def bark=println(s"$name is barking")}
defined class Dog scala> "barkdo".bark
barkdo is barking

2)注意事项: 隐式类的主构造函数参数有且仅有一个!之所以只能有一个参数,是因为隐式转换是将一种类型转换为另外一种类型,源类型与目标类型是一一对应的

scala> implicit class Dog2(val name: String, val age: Int){
| def bark=println(s"$name is barking")}
<console>:15: error: implicit classes must accept exactly one primary constructor parameter
implicit class Dog2(val name: String, val age: Int){

2  隐式对象

        格式:

implicit object 对象名{
//类主体
}

例子

object ImplicitTest extends App{
//定义一个trait Multiplicable
trait Multiplicable[T]{
def multiply(x: T):T
}
//定义一个隐式对象,用于整型数据相乘
implicit object MultiplicableInt extends Multiplicable[Int]{
def multiply(x: Int): Int = x*x
}
//定义一个用于字符串相乘的隐式对象
implicit object MultiplicableString extends Multiplicable[String]{
def multiply(x: String): String = x*2
}
//定义一个函数,函数具有泛型参数
def multiply[T: Multiplicable](x: T): T ={
//implicitly方法,访问隐式对象
val ev = implicitly[Multiplicable[T]]
//根据具体的类型调用相应的隐式对象中的方法
ev.multiply(x)
} //调用隐式对象 MultiplicableInt 中的方法
println(multiply(5)) //调用隐式对象 MultiplicableString 中的方法
println(multiply("5"))
}
 运行结果: 25 55 

三,隐式参数与隐式值

   1, 隐式参数,在函数的定义时,在参数前添加implicit关键字。

      格式:

def 函数名(implicit 参数名:l类型):返回值={
//函数体
}

例子://修改上面的一个方法

 //定义一个函数,函数具有泛型参数
def multiply[T: Multiplicable](x: T)(implicit ev: Multiplicable[T]): T ={
//根据具体的类型调用相应的隐式对象中的方法
ev.multiply(x)
}

2)隐式值:

      格式

implicit val 变量名:类型=值

例子

//定义一个带隐式参数的函数
scala> def sqrt(implicit x: Double) = Math.sqrt(x)
sqrt: (implicit x: Double)Double
//定义一个隐式值
scala> implicit val x:Double = 2.55
x: Double = 2.55
//调用定义的sqrt函数,它将自行调用定义好的隐式值
scala> sqrt
res1: Double = 1.5968719422671311

3,隐式参数使用的常见问题:

1)当函数没有柯里化时,implicit关键字会作用于函数列表中的的所有参数。

2)隐式参数使用时要么全部不指定,要么全不指定,不能只指定部分。

      3)同类型的隐式值只能在作用域内出现一次,即不能在同一个作用域中定义多个相同类型的隐式值。

4)在指定隐式参数时,implicit 关键字只能出现在参数开头。

5)如果想要实现参数的部分隐式参数,只能使用函数的柯里化,

如要实现这种形式的函数,def test(x:Int, implicit  y: Double)的形式,必须使用柯里化实现:def test(x: Int)(implicit y: Double).

6) 柯里化的函数, implicit 关键字只能作用于最后一个参数。否则,不合法。

7)implicit 关键字在隐式参数中只能出现一次,柯里化的函数也不例外!

scala> def product(implicit x: Double, implicit y: Double)=x*y
<console>:1: error: identifier expected but 'implicit' found.
def product(implicit x: Double, implicit y: Double)=x*y
scala> def product(implicit x: Double)(implicit y: Double)=x*y //柯里化函数
<console>:1: error: '=' expected but '(' found.
def product(implicit x: Double)(implicit y: Double)=x*y

8)匿名函数不能使用隐式参数

scala> val prodeuct = (x: Double, y: Double) => x*y
prodeuct: (Double, Double) => Double = <function2> scala> val prodeuct = (implicit x: Double, y: Double) => x*y
<console>:1: error: '=>' expected but ',' found.
val prodeuct = (implicit x: Double, y: Double) => x*y
^

9)柯里化的函数如果有隐式参数,则不能使用其偏应用函数

//柯里化函数product
scala> def product(x: Double)(y: Double)=x*y
product: (x: Double)(y: Double)Double
//两个参数的偏应用函数
scala> val p1=product _
p1: Double => (Double => Double) = <function1>
//调用
scala> p1(3.0)(4.0)
res1: Double = 12.0
//一个参数的偏应用函数
scala> val p2 = product(3.0) _
p2: Double => Double = <function1>
//调用
scala> p2(4.0)
res2: Double = 12.0
//将柯里化函数参数y, 声明为隐式参数
scala> def product(x: Double)(implicit y: Double)=x*y
product: (x: Double)(implicit y: Double)Double
//定义隐式参数后,便不能使用其偏应用函数
scala> val p1=product _
<console>:13: error: could not find implicit value for parameter y: Double
val p1=product _
^
scala>

四,隐式函数的若干规则:

1)显示定义规则

在使用带有隐式参数的函数时,如果没有明确指定与参数类型匹配相同的隐式值,编译器不会通过额外的隐式转换来确定函数的要求。

2)作用域规则

不管是隐式值,隐式对象,隐式类或隐式转换函数,都必须在当前的作用域使用才能起作用!

3)无歧义规则

所谓无歧义值的是,不能存在多个隐式转换是代码合法,如代码中不应该存在两个隐式转换函数能够同时使某一类型转换为另一类型,也不应该存在相同的两个隐式值,主构造函数参数类型以及成员方法等同的两个隐式类。

4)一次性转换规则

隐式转换从源类型到目标类型只会经过一次转换,不会经过多次隐式转换达到。

最新文章

  1. TypeScript 素描 - 类
  2. 转:Eclipse插件开发之TreeViewer
  3. jquery中ajax在firefox浏览器下“object XMLDocument”返回结果的解决办法
  4. How do I remove javascript validation from my eclipse project?
  5. guava常用操作
  6. mysql5.x(&lt;7) sql文件导入到5.7
  7. webapi中的路由约束
  8. .NET跨平台实践:Linux .Net Core自宿主应用程序瘦身记
  9. K-means之亚洲杯
  10. php记录
  11. WSGI、uwsgi和uWSGI
  12. Python3+selenium+BaiduAI识别并下载花瓣网高颜值妹子图片
  13. [UE4]自动旋转组件
  14. mysql 查找在另一张表不存在的数据
  15. 用pyinstaller把python代码打包成exe可执行文件
  16. vue如何加搜狗联盟广告
  17. WDA-文档-基础篇/进阶篇/讨论篇
  18. UI5-文档-4.30-Debugging Tools
  19. go语言项目汇总
  20. Python 数值类型

热门文章

  1. 容器编排系统K8s之Dashboard部署
  2. 二本非科班,秋招,实习,面试,offer之路
  3. ARM CPU的SVC模式
  4. 线程安全问题synchronized锁
  5. 风炫安全WEB安全学习第二十六节课 XSS常见绕过防御技巧
  6. Command3
  7. MYSQL 字符集设置(终端的字符集)
  8. Solon rpc 之 SocketD 协议 - 消息加密模式
  9. 【Oracle】DRM官方介绍
  10. 如何构建一个多人(.io) Web 游戏,第 2 部分