scala中的隐式函数

15 阅读2分钟

由于有精度损失,Double无法直接保存在Int中,而Int可直接保存在Double中,该如何解决这个问题呢

(一)什么是隐式转换

隐式转换是指:scala自动把一种类型转成另一种类型的过程。这个过程对用户编程而言不可见,不需要用户手动编写代码。

请大家一起回顾如下代码

var i:Int= 1;

val b:Double = i

在上面的代码的过程中,scala就帮我们做了一次隐式转换:把Int -> Double。

但是反过来,不能把Double → Int

var i:Int= 1.5;  // 这里会报错

 

(二)隐式函数

在scala.Predef中,可以看到有系统提供了默认的情况。

隐式函数的定义:通过implicit关键字修饰的函数,它的功能是把一种类型的数据转成另一种类型。

implicit def 函数名(参数:类型1):类型2 = {

函数体

}

注意点:

(1)调用时机,在系统自动把数据从类型1隐式转为类型2时出错时,被自动调用。

(2)函数名可以自定义(一般取名为类型1to类型2),但是参数和返回值必须有限制。

package imp

object Demo01 {
  def main(args: Array[String]): Unit = {
    //隐式
    //由于有精度损失,Double无法直接保存在Int中,而Int可直接保存在Double中
    //
    implicit def cent(D:Double):Int =  {
      println("方法被调用")
      D.toInt
    }
    val I:Int = 1.1
    println(I)
  }

}

应用场景

上游数据类型的变化,导致下游消费数据的变化。此时,可以在不修改原来代码的情况下,去很方便地解决这个问题。

练习一:将Km转换为m
package imp

object Demo02 {
  def main(args: Array[String]): Unit = {
    class M(val value:Double) {
      override def toString: String = value + "米"
    }
    class KM(val value:Double) {
      override def toString: String = value + "米"
    }
    implicit def Km2m(KM: KM):M = {
      println("KM => M 被调用")
    new M(1000 * KM.value)
    }
    val Km1 = new KM(1)
    val m1:M = Km1
    println(m1)
  }

}

结果:

image.png

练习二:将美元与人民币互相转换
package imp

object Demo03 {
  def main(args: Array[String]): Unit = {
    class my(val value:Double) {
      override def toString: String = value + "美元"
    }
    class y(val value:Double) {
      override def toString: String = value + "元"
    }
    implicit def my2y(my:my):y ={
      println("美元转人民币已被调用")
      new y(6.9 * my.value)
    }
    implicit def y2my(y:y):my = {
      println("人民币转美元已被调用")
      new my(0.14 * y.value)
    }
    val my1 = new my(2)
    val y1 = new y(2)
    var y2:y = my1
    println("2美元等于" + y2 )
    var my2:my = y1
    println("2元等于" + my2 )
  }

}

结果:

image.png