20.2 隐式转换函数
所谓隐式转换函数(implicit conversion function)指的是那种以implicit声明的带有单个参数的函数。
从名字中可以看出,因为是“隐式”的,所以这种函数不需要我们显式的调用。在发生类型不匹配的时候,会自动将一种类型转换成类一种类型。
举例来说,我们现在有2个类A和B
class A() { override def toString(): String = { "I am B" } } class B { override def toString(): String = { "I am B" } }
然后我们定义了一个函数testConversion,接受类型为A的参数
object ConversionDemo { def testConversion(a: A) {//定义一个函数,接受类型为A的参数 println("current type:" + a) } def main(args: Array[String]) { testConversion(new B)//传入B的实例。编译无法通过 } }
因为testConversion接受类型为A的参数,而我们现在传入的是B类型,因此编译无法通过。现在我们希望B能自动转换为A。此时我们需要定义隐式转换函数。根据隐式转换函数的要求,我们要定义一个方法,这个方法接受一个类型为B的参数,返回类型为A的参数。
implicit def b2A(b: B) = { new A }
问题是:这个函数放在哪里比较合适呢?
Scala在进行隐式转换的时候,会考虑如下的隐式转换函数:
1、位于源或者目标类型的伴生对象中的隐式函数。
2、位于当前作用域可以以单个标识符指代的隐式函数。
在这里,我们按照第一种规则来放置隐式函数的位置。也就是我们需要定义A或者B的一个伴生对象(随便哪一个都可以)。假设我们在A的伴生对象中定义:
object A { implicit def b2A(b: B) = {//注意接受的参数是需要转换的源类型,返回的值是目标类型。 new A } }
此时我们再来运行程序。控制台输出:
current type:I am B
说明隐式转换成功。
在上面这个案例中,因为是方法接受的参数需要进行类型转换,传入的参数类型B和方法接受的参数类型A都是已经确定的,所以无论隐式函数转换函数无论放在哪个类中都是可以的。
如果是方法的调用者需要进行类型转换的话,如A调用了一个自己本身没有的方法,那么隐式转换函数必须放在A的伴生对象中。
除了将隐式转换函数放置于类的伴生对象中,我们还可以将其单独定义在一个object类中。如:
package com.tianshouzhi.scala.conversion import com.tianshouzhi.scala.demo.A import com.tianshouzhi.scala.demo.B object ABConversion { implicit def b2A(b: B) = { new A } implicit def a2B(b: A) = { new B } }
在使用时,我们只需要导入这个类即可
package com.tianshouzhi.scala.demo //注意,必须要带上"_",类似于Java的静态导入。 import com.tianshouzhi.scala.conversion.ABConversion._ class A() { override def toString(): String = { "I am B" } } class B { override def toString(): String = { "I am B" } } object ConversionDemo { def testConversion(a: A) { println("current type:" + a) } def main(args: Array[String]) { testConversion(new B) } }
提示:在这里我们是在文件定义的头部导入隐式转换函数,这意味着,在所有需要隐式转换的地方,都会自动进行。如果你想限定自动转换的有效范围,例如只有在某个方法中才能进行隐式转换,那么只要在这个方法的内部导入即可。