0%

scala隐式函数

scala隐式函数

在低精度数值向高精度数值转换时是自动进行转换的,而高精度数值向低精度数值转换时就需要手动的进行强制类型转换,可以使用隐式函数来优雅的解决这种问题

隐式函数implicit

隐式函数是以implicit关键字声明的单个参数的函数,这种函数将会自动应用,将值从一种类型转为另一种类型

1
2
3
4
5
6
7
8
// 隐式函数  将Double自动转化为Int
implicit def f1(d:Double): Int ={
d.toInt
}

// 引入隐式函数
import com.zhanghe.study.study_scala.oop.TestImplicit.f1
var i:Int = 2.0

这是编译器来调用该隐式函数的,所以一定要注意隐式函数的作用域

隐式参数

将某个形参变量标记为implicit,编译器会在方法省略隐式参数的情况下去搜索作用域内的隐式值作为缺省参数

1
2
3
4
5
6
7
8
9
implicit val str1 :String = "jjj"

// 由于没有给隐式变量赋值,所以该name使用的是str1
// 如果该作用域下没有隐式值,编译会报错
hello

def hello(implicit name:String): Unit = {
println(s"hello $name")
}

优先级 传值>隐式值>默认值

隐式类

scala还支持使用implicit来声明类,作为隐式类,可以用来扩展类的功能

  • 隐式类所带的构造参数只能有一个
  • 隐式类必须被定义在 类、伴生对象、包对象里,隐式类不能是顶级的
  • 隐式类不能是case class(样例类)
  • 作用域内不能有与隐式类相同名称的标识符
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Money {
var suffix = ""
}


implicit class RMB(money: Money) {
def addSuffix()= {
money.suffix = "元"
}
}

val money = new Money
// 可以直接调用隐式类中的方法
money.addSuffix()

什么时候会触发隐式类的调用

  • 当方法中的参数类型与目标类型不一致时
  • 当对象调用所在类中不存在的方法和成员时

隐式转换规则

当有以下三种情况时编译器会考虑隐式转换

  • 当表达式的类型与预期类型不同时
  • 当对象访问一个不存在的成员时
  • 当对象调用某个方法,而方法的参数声明与传入参数不匹配时

有以下三种情况时编译器不会考虑隐式转换

  • 如果代码能够不使用隐式转换的前提下通过编译,则不会使用隐式转换
  • 编译器不会尝试同时执行多个转换
  • 存在二义性的转换不会考虑

欢迎关注我的其它发布渠道