Scala | 隐式转换

18 阅读2分钟

一、什么是隐式转换

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

二、隐式函数

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

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

函数体

}

注意点:

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

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

  • 隐式转换函数

  • 1.用关键字implicit 修饰

  • 2.它的函数名不重要(),重要的是它的 参数和返回值 的类型

  • 3.系统会自动调用它

  • // 注意:不能写两个同类型(参数和返回值的类型都一样)的隐式转换函数,他会报错!!!

  • // 它的参数是Double 他的返回值是Int 他的作用是:当代码中出现了需要把Double转换成Int的时候,系统会自动调用它

object imp01 {

  implicit def double2Int(x:Double):Int = {
    println("double to int")
    x.toInt
  }

//  implicit def doubleToInt(x:Double):Int = {
//    println("double to int")
//    x.toInt
//  }
  
  def main(args: Array[String]): Unit = {
    // 1.隐式转换
    var i:Int = 1

    var d:Double = 1.1;

    d = i // 把int → double类型,它会自动也去调用隐式转换函数

//    d = i.toDouble
//    println(s"d=${d}")

    i = d // 存在一个隐式转换 把double → int 报错!!!
    i = 100.1
  }
}

三、隐式参数

隐式参数,在开发的过程中,如果预判一个参数将来会变动,就可以把他设置为implicit

  • 在写代码的过程中,有一个原则:尽量不要修改之前的代码
object imp02 {
  implicit val defaultPassword:String = "88888888"

  def reg(name:String, password:String="123456"):Unit = {
    println(s"您注册成功, 姓名:${name}, 密码:${password}")
  }
//  def reg(name:String, password:String="123456"):Unit = {
//    println(s"您注册成功, 姓名:${name}, 密码:${password}")
//  }

  def main(args: Array[String]): Unit = {

    reg("HH") // 没有传入密码,使用默认值123456
    reg("MM","admin")
  }
}

四、隐式转换规则

1.无歧义规则。不能重新定义两个相同的转换函数
object imp03 {
  implicit def fun1(a:String):Int = a.toInt
  implicit def fun2(a:String):Int = a.toInt


  def main(args: Array[String]): Unit = {

    val i:Int = "100"
  }
}
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}米" }

  implicit def km2bm(km:KM): BM = new BM(km.value * 10)
  implicit def bm2m(bm: BM): M = new M(bm.value * 100)
  implicit def km2m(km: KM): M = new M(km.value * 1000)

  def main(args: Array[String]): Unit = {

    val km = new KM(1.1)
    val bm:BM = km
    println(km)
    println(bm)

    val m:M = bm
    println(m)

    val m1:M = new KM(2)
    println(m1)
  }

}

五、作用域

先说一个不能放的位置:implicit 不能放在顶级作用域(不能放在类的外边)看如下代码,就会报错

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

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

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

在其他需要使用的地方导入: import implication.Implications._

image.png

屏幕截图 2025-12-29 102740.png