scala的隐式转换基本使用1.2

21 阅读2分钟

(四)转换规则

隐式转换确实非常的强大,但是,在具体的使用过程中,我们要遵循一些特定的转换规则。

具体来说有两点:无歧义规则,不能多次转换。下面我们分别来解释

  规则1:无歧义规则:不能重新定义两个相同的转换函数。如果有两个隐式转换函数,只有函数名不同,则会导致错误。

规则2:不能多次转换:在一次转换过程中可以把A->B,B->C,但是不能直接从A->C。来通过具体的代码来说明。

在上面的代码中,可以把M->BM, 把BM->KM,但是依靠这两个规则自动推导M->KM就会报错。也就是说:隐式转换时只能转换一次。

package imp

/*
隐式转换函数的规则
1.无歧义规则。
  不能写两个相同的转换函数!

2.不能自动多次转换
A -> B , B->C , 不等价于 A -> C
 * */
object imp03 {
  class KM(var value:Double) {
    override def toString: String = s"${value} 千米"
  }

  class BM(var value:Double) {
    override def toString: String = s"${value} 百米"
  }

  class M(var value:Double) {
    override def toString: String = s"${value} 米"
  }

  // 补充隐式转换函数,把KM -> M
  implicit def km2m(km:KM):M = { new M(km.value * 1000) }
  // 补充隐式函数,把M -> KM
  implicit def k2km(m:M):KM = { new KM(m.value / 1000) }
  // 补充隐式函数,把KM ->BM
  implicit def Km2bm(km:KM):BM = { new BM(km.value * 10) }
  // 补充隐式函数,把BM -> M
  implicit def bm2m(bm:BM):M = { new M(bm.value * 100) }

  def main(args: Array[String]): Unit = {
    val km1 = new KM(2)
    val m1:M = km1
    val m2:M = new BM(2)

    val km2:KM = new M(2500)
    val bm1:BM = km1

    println(m1)
    println(m2)
    println(km2)
    println(bm1)
    println(m1)
  }
}

(五)作用域

接下来我们讨论一个问题:就是把隐式函数的定义放在哪里使用起来更加方便?当然了,在默认情况下,会在当前类的内部去找。

先说一个不能放的位置:implicit 不能放在顶级作用域(不能放在类的外边)

在实际的操作过程中,我们建议把它定义在如下两个地方:

1.包对象。 这样在这个包下的所有类和对象中都可以使用,并且不需要额外的引入语句。

2. 一个单独的文件定义中。 这样在其他需要的位置就可以直接导入,然后使用。