隐式转换
隐式函数基本介绍
隐式转换函数是以implicit关键字声明的带有单个参数的函数,这种函数将会自动调用,将值从一种类
型转换到另一种类型,使用隐式函数可以优雅的解决数据类型转换
隐式转换的注意事项和细节
1 隐式转换函数的函数名可以是任意的,隐式转换与函数名称无关,只与函数 签名(函数参数类型和
返回值类型)有关
2 隐式函数可以有多个(即:隐式函数列表),但是需要保证在当前环境下,只有一个隐式函数能被识
别
object ImplicitDemo01 {
def main(args: Array[String]): Unit = {
//编写一个隐式函数转成Double -> Int 转换
//隐式函数应当在作用域才能生效
implicit def f1(d:Double): Int ={ //底层生成f1$1
d.toInt
}
implicit def f2(f:Float): Int ={
f.toInt
}
// 这里我们必须保证隐式函数的匹配只能是唯一的
// implicit def f3(f1:Float): Int ={
// f1.toInt
// }
val num: Int = 3.5 //底层编译f1$1(3.5)
val num2: Int = 4.5f
println("num=" + num)
}
}
隐式转换丰富类库功能
基本介绍
如果需要为一个类增加一个方法,可以通过隐式转换来实现.(动态增加功能)比如想为MySQL类增加一个delete方法
分析解决方案
在当前程序中,如果想要给MySQL类增加功能是非常简单的,但是在实际项目中,如果想要增
加新的功能就会需要改变源代码,这是很难受的,而且违背了软件开发的OCP开发原则(闭合原则
open close priceple)在这种情况下,可以通过隐式转换函数给类动态添加功能
object ImplicitDemo02 {
def main(args: Array[String]): Unit = {
//编写一个隐式函数,丰富mysql功能
implicit def addDelete(msql:MySQL): DB = {
new DB
}
// 创建mysql对象
val mySQL = new MySQL
mySQL.insert()
mySQL.delete() //分析 addDelete$1(mySQL).delete()
mySQL.update()
}
}
class MySQL{
def insert(): Unit ={
println("insert")
}
}
class DB{
def delete(): Unit ={
println("delete")
}
def update(){
println("update")
}
}
隐式值
基本介绍
隐式值也叫隐式变量,将某个形参变量标记为implicit,所以编译器会在方法省略隐式参数的情况下去
搜索作用域内的隐式值作为缺省参数
示例:
object ImplicitValDemo03 {
def main(args: Array[String]): Unit = {
implicit val str1: String = "jack**" //这个就是隐式值
// implicit name: String :name就是隐式参数
def hello(implicit name: String): Unit ={
println(name + "hello")
}
hello //底层hello$1(str1) 使用隐式值不要带()
}
}
案例1
隐式匹配具有唯一性
示例:
object ImplicitVal02 {
def main(args: Array[String]): Unit = {
implicit val name: String = "Scala"
implicit val name1: String = "World"
// 隐式参数
def hello(implicit content: String = "jack"): Unit ={
println("Hello" + content)
}//调用hello
hello
}
}
这个时候程序会报错,显示错误:
程序会显示模糊的隐式值这样一个错误,原因是因为程序中两个隐式变量name和name1的类型
都是String类型,编译器去匹配时无法识别到底是哪一个,因此会报错。这个时候注销一个,程序就
会正常运行,这也再次证明了隐式匹配具有唯一性。
示例:
案例2
当同时有implicit值和默认值,implicit优先级高
示例:
object ImplicitVal02 {
def main(args: Array[String]): Unit = {
implicit val name: String = "Scala"
//当同时有implicit值和默认值,implicit优先级高
def hello2(implicit content: String = "jack"): Unit ={
println("Hello2" + content)
}//调用hello2
hello2
}
}
运行结果:
案例3
当一个隐式参数匹配不到隐式值,仍然会使用默认值
示例:
案例4
当程序中隐式参数content没给默认值时,这个时候程序会报错,原因是当调用函数时,它首先会去找隐式值,发
现上面有一个,但是是个Int类型的不能匹配,于是隐式值是匹配不到的,默认值又没给,同时还不传
值,因此就报错了。但当三者都存在的时候,即既有隐式值,又有默认值,还传了值,那这个时候传
的值优先级最高,然后是隐式值,最后是默认值。
示例:
小结:
1 当在程序中,同时有隐式值,默认值,传值
2 编译器的优先级为 传值 > 隐式值 > 默认值
3 在隐式值匹配时,不能有二义性(即不能匹配多个)
4 如果三个(隐式值,默认值,传值) 一个都没有,就会报错