scala的隐式转换基本使用

31 阅读4分钟

(一)什么是隐式转换

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

var i:Int= 1;
val b:Double = i

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

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

(二)隐式函数

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

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

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

函数体

}

注意点:

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

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

/*
*
* 隐式函数:把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.5 //把double --> int 隐式转换 把精度高的数据装成精度低的数据 不可以
    i = 1.2

    println(i)
  }

}

//运行结果:
调用 double2int
调用 double2int
1

(三)隐式参数

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

  • 在开发的过程中,如果知道有个参数会被改动,就可以添加implicit,但是implicit在参数列表中只能出现一次,并要写在参数列表的最前面,对所有的参数列表生效。

  • 如果一个函数有多个参数,并且你只想对某个参数进行隐式转换,那么,可以使用柯里化的方式来定义参数,并且把转换的参数定义在参数列表的最后。

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")

  }
}

//运行结果:
注册成功,用户名:小花,密码:88888888
注册成功,用户名:小明,密码:admin

(四)隐式转换函数的转换规则

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

具体来说有两点:1.无歧义规则 。 2.不能多次转换。

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

规则2:不能多次转换:在一次转换过程中可以把A->B,B->C,但是不能直接从A->C。

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

// 补充隐式转换函数 把KM -> M
  implicit def km2m(km:KM):M = {new M(km.value * 1000)}

  implicit def m2km(m:M):KM = {new KM(m.value / 1000)}
  // 补充隐式转换函数 把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)
    println(m1)
    println(m2)
    println(km2)

  }
}

//运行结果:
2000.0200.02.5 千米

(五)作用域

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

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

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

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

案例代码:

import scala.language.postfixOps
import imp.imp05._
/*
*目标:让任意一个整数具备一个功能 计算阶乘
* n!= 1 * 2* 3 * 4 *...n
*
* */
object imp07 {

  def main(args: Array[String]): Unit = {
    println(4!)//24
    println(5!) //120
    println("429116200904230664".isIDcard)
    println("42911620090423066a".isIDcard)
  }

}

//运行结果:
24
120
true
false

屏幕截图 2025-12-30 101916.png