隐式转换
在之前的类型学习中,我们已经学习了自动类型转换,精度小的类型可以自动转换为精度大的类型,这个转换过程无需开发人员参与,由编译器自动完成,这个转换操作我们称之为隐式转换。
在其他的场合,隐式转换也起到了非常重要的作用。如Scala在程序编译错误时,可以通过隐式转换中类型转换机制尝试进行二次编译,将本身错误无法编译通过的代码通过类型转换后编译通过。慢慢地,这也形成了一种扩展功能的转换机制。

1. 隐式函数
使用implicit关键字声明的函数称之为隐式函数。这样可以在不需改任何代码的情况下,扩展某个类的功能。
比如
scala
def main(args: Array[String]): Unit = {
// 转换函数
implicit def transformAge(age: Double): Int = {
age.toInt
}
val i:Int = 10.5
println(i)
}运行结果:

2. 隐式参数&隐式变量
普通方法或者函数中的参数使用implicit关键字声明为隐式参数,调用该方法时,编译器会在相应的作用域寻找符合条件的隐式变量, 隐式变量就是被implicit关键字修饰的变量,没有找到就正常普通函数调用。
scala
def main(args: Array[String]): Unit = {
// 隐式参数
def reg(name:String)(implicit password:String="000000"):Unit={
println(s"name: $name, password: $password")
}
reg("jack")("111111")
reg("maomao")
println("***********************")
// 隐式参数需要配合隐式变量一起使用
implicit val pass = "123123"
reg("tuanzi")
}运行结果:

3. 隐式类
3.1 隐式类概述
在Scala2.10之后提供了隐式类,可以使用implicit声明类。
- 在没有隐式类之前,如果需要扩展类的功能,遵从OCP原则的话,可以这么实现:
scala
def main(args: Array[String]): Unit = {
// User类和UserExt的隐式转换,需要构造他们的关系
implicit def transformUser(user: User): UserExt = {
new UserExt()
}
val user = new User()
user.insertUser()
// 利用class+function,实现扩展类的功能
user.updateUser()
}
class UserExt() {
def updateUser(): Unit = {
println("updateUser")
}
}
class User {
def insertUser(): Unit = {
println("insertUser")
}
}运行结果:
2. 使用隐式类实现, 代码更加简洁
scala
def main(args: Array[String]): Unit = {
val user = new User()
user.insertUser()
user.updateUser()
}
// 使用隐式类,编译器自动生成transformUser类似方法,实现绑定关系进行互转
// 值得注意的是隐式类的构造函数里的参数只能有一个。
implicit class UserExt(user: User) {
def updateUser(): Unit = {
println("updateUser")
}
}
class User {
def insertUser(): Unit = {
println("insertUser")
}
}
object User{
// 在伴生对象内,定义隐式类
// implicit class UserExt(user: User) {
// def updateUser(): Unit = {
// println("updateUser")
// }
// }
}3.2 隐式类定义的位置
在隐式转换二次编译的时候,Scala编译器根据隐式类生成隐式转换的逻辑,前提需要知道要用到的隐式类的位置,才能够自动生成转换的逻辑,如果不明确限制查找范围,Scala编译器的效率可想而知,java中的包就要扫描很久。
- 隐式类的定义的位置:
- 当前类的内部, 隐式类不能定义为最外层对象
- 父类,父类的伴生对象
- 特质,特质的伴生对象
- 包对象
比较特殊的是包对象,将隐式类放到包对象过程如下:
创建包对象:

scala
object TransformDemo6 {
def main(args: Array[String]): Unit = {
val user = new User()
user.insertUser()
user.updateUser()
}
class User {
def insertUser(): Unit = {
println("insertUser")
}
}
}
scala
package object transformData {
implicit class UserExt(user: User) {
def updateUser(): Unit = {
println("updateUser")
}
}
}

评论