Scala 隐式转换

33 阅读3分钟

一、导入

在Scala编程中,类型转换是一个常见的需求。我们都知道,将精度低的类型转换为精度高的类型(如IntDouble)是自动进行的隐式转换,但反过来呢?这节课我们将深入探讨Scala强大的隐式转换机制,学习如何让编译器在类型不匹配时自动进行类型转换,从而提高代码的灵活性和可维护性。

二、讲授新课

(一)什么是隐式转换

隐式转换是Scala自动将一种类型转换为另一种类型的过程。这个过程对开发者透明,无需手动编写转换代码。

案例:隐式转换函数的使用

package imp
/*
  隐式转换函数:把 double 转成 int
  隐式函数
  1.implicit 修饰
  2.它会自动被调用当系统检测到隐式转换失败的时候去自动调用
  3.函数的名字不重要重要的是它的输入数据的类型和返回值类型

  它的作用是:偷偷地把一种类型的数据转成另一种类型的数据
 */
object imp01 {
  implicit def double2int(d:Double):Int = {
    println("调用 double2int")
    d.toInt
  }
  def main(args: Array[String]): Unit = {
    var i:Int = 1;

    val d:Double = i // 把Int-->double 隐式函数 把精度低的数据转成精度高的数据,这是可以的
    i = 1.2
    i = 2.2
    i = 3.2// 把double--> int 把高精度的转成低精度的 错误
    println(i)

  }
}

(二)隐式参数

隐式参数用于处理那些可能会频繁修改的默认参数值。通过使用隐式参数,可以在不修改函数调用代码的情况下改变参数的默认值。

案例:隐式参数的使用

package imp

/*

  隐式参数:如果在写函数的参数的时候,预计某个参数的默认值可能会被修改可以设置隐式参数

 */

object imp02 {

  implicit val defaultPassword:String = "88888888"

  def reg(name:String)(implicit password:String="123456"):Unit = {
    println(s"用户名:${name}, 密码:${password}")
  }

  def main(args: Array[String]): Unit = {
    reg("小花")
    reg("小明")("admin")

  }
}

(三)转换规则

隐式转换虽然强大,但必须遵循特定的转换规则:

规则1:无歧义规则

不能在同一作用域定义两个相同的转换函数(函数名不同但输入输出类型相同)

规则2:不能多次转换

隐式转换一次只能进行一次转换,不能自动进行链式转换(如A->B->C)

案例:隐式转换规则演示

package imp

/*
隐式转换函数的规则
1.无歧义规则
     不能写两个相同的转换函数
2.不能自动多次转换
     A -> B  B -> C 不等价于 A -> C
 */

object imp03 {
  class KM(val value: Double) {
    override def toString: String = s"${value} 千米"
  }
  class M(val value: Double) {
    override def toString: String = s"${value} 米"
  }
  class BM(val value: Double) {
    override def toString: String = s"${value} 百米"
  }

  // 隐式转换:千米 -> 米
  implicit def km2m(km: KM): M = new M(km.value * 1000)

  // 隐式转换:百米 -> 米
  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)

    println(m1)
    println(m2)
  }
}