先回顾一下隐式对象的使用代码:
/*
*隐式对象
*/
object Example11_1 extends App{
//定义一个trait Multiplicable
trait Multiplicable[T] {
def multiply(x: T): T
}
//定义一个隐式对象MultiplicableInt,用于整型数据的相乘
implicit objectMultiplicableInt extends Multiplicable[Int] {
def multiply(x: Int) =x*x
}
//定义一个隐式对象MultiplicableString,用于字符串数据的乘积
implicit objectMultiplicableString extends Multiplicable[String] {
def multiply(x: String)= x*2
}
//定义一个函数,函数具有泛型参数
def multiply[T:Multiplicable](x:T) = {
//implicitly方法,访问隐式对象
val ev =implicitly[Multiplicable[T]]
//根据具体的类型调用相应的隐式对象中的方法
ev.multiply(x)
}
//调用隐式对象MultiplicableInt中的multiply方法
println(multiply(5))
//调用隐式对象MultiplicableString中的multiply方法
println(multiply("5"))
}
在Example11_1代码中,我们在val ev =implicitly[Multiplicable[T]]代码中调用implicitly函数来确定最终的隐式对象,该函数也被定义在Predef对象中,现在让我们来下该函数的定义:
@inline def implicitly[T](implicit e: T) = e
可以看到,implicitly函数中有一个参数implicit e: T,同一般函数所不同的是,参数e前面也使用了implicit关键字修饰,我们称这种形式的参数为隐式参数。通过val ev = implicitly[Multiplicable[T]]可以看到,我们调用的时候并没有指定该隐式参数,那值是怎么传进行来的呢?这便是隐式参数的作用,前面提到函数def multiply[T: Multiplicable](x:T)要求在当前作用域存在一个类型为Multiplicable[T]隐式值或隐式对象,在调用该函数时具体的参数类型被确定,如调用multiply(5)时参数类型为Int,则会在当前作用域内查找类型为Multiplicable[T]的隐式值或隐式对象,此时MultiplicableInt满足要求,因此最终implicitly方法返回的对象为MultiplicableInt然后调用def multiply(x: String) = x*2方法得到最终结果。其实Example11_1中的multiply方法还可以利用隐式参数进行进一步简化,即将:
//定义一个函数,函数具有泛型参数
def multiply[T:Multiplicable](x:T) = {
//implicitly方法,访问隐式对象
val ev =implicitly[Multiplicable[T]]
//根据具体的类型调用相应的隐式对象中的方法
ev.multiply(x)
}
修改为:
//使用隐式参数定义multiply函数
def multiply[T:Multiplicable](x:T)(implicit ev:Multiplicable[T]) = {
//根据具体的类型调用相应的隐式对象中的方法
ev.multiply(x)
}
完整代码如下:
/*
*隐式参数
*/
object Example11_2 extends App{
//定义一个trait Multiplicable
trait Multiplicable[T] {
def multiply(x: T): T
}
//定义一个隐式对象MultiplicableInt,用于整型数据的相乘
implicit object MultiplicableInt extendsMultiplicable[Int] {
def multiply(x: Int) = x*x
}
//定义一个隐式对象MultiplicableString,用于字符串数据的乘积
implicit object MultiplicableString extendsMultiplicable[String] {
def multiply(x: String) = x*2
}
//使用隐式参数定义multiply函数
def multiply[T:Multiplicable](x:T)(implicit ev:Multiplicable[T]) = {
//根据具体的类型调用相应的隐式对象中的方法
ev.multiply(x)
}
//调用隐式对象MultiplicableInt中的multiply方法
println(multiply(5))
//调用隐式对象MultiplicableString中的multiply方法
println(multiply("5"))
}
代码运行结果与Example11_1相同,函数def multiply[T:Multiplicable](x:T)(implicit ev:Multiplicable[T])使用的隐式参数,它会在当前作用域内查找类型Multiplicable[T]的隐式对象,因此在执行multiply(5)时,由于泛型参数类型为Int,它便会在当前作用域内查找Multiplicable[Int]类型的隐式对象,只有implicit objectMultiplicableInt extends Multiplicable[Int]满足要求,因此会将MultiplicableInt赋值给ev,然后再调用def multiply(x: Int)= x*x执行最终计算。
Scala学习(公众微信号:ScalaLearning)每天为大家带来一点Scala语言、Spark、Kafka、Flink、AKKA等大数据技术干货及相关技术资讯
技术永无止境,勇攀高峰,一往直前!
觉得文章不错?扫描关注