20.2 隐式转换函数

2016-05-08 13:10:24 3,298 0


所谓隐式转换函数(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)
    }
  }

提示:在这里我们是在文件定义的头部导入隐式转换函数,这意味着,在所有需要隐式转换的地方,都会自动进行。如果你想限定自动转换的有效范围,例如只有在某个方法中才能进行隐式转换,那么只要在这个方法的内部导入即可。

上一篇:20.1 隐式转换规则 下一篇:20.3 隐式参数