scala的隐式转换

23 阅读2分钟

隐式转换的定义

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

隐式函数的定义

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

隐式函数的注意点

  1. 调用时机,在系统自动把数据从类型1隐式转为类型2时出错时,被自动调用。
  2. 函数名可以自定义(一般取名为类型1 to 类型2),但是参数和返回值必须有限制。

隐式转换的基本代码

object imp01 {

  // 隐式转换函数
  //  1. 用关键字implicit 修饰
  //  2. 它的函数名不重要(一般的命名是类型1to类型2) ,重要的是它的 参数和返回值 的类型。
  //  3. 系统会自动调用它

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

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

  implicit def doubleTOInt(x:Double):Int={
    println("double to int")
    x.toInt
  }
//  implicit def xxx(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 = 99.9
    i = 9.9
  }

}

隐式参数的基本代码

// 在写代码的过程中,有一个原则:尽量不要修改之前的代码
// 隐式参数
//  在开发过程中,如果预判一个参数将来会变动,就可以把它设置为implicit

object imp02 {

  implicit val defaultPassword:String="88888888"  //  在修改隐式参数的值的时候,前面定义的变量名 不重要,类型是最重要的

  def reg(name:String)(implicit 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("小花")  //没有传入密码,默认值为123456
    reg("小白")("admin")
  }
}

隐式转换规则

  1. 无歧义规则:不能重新定义两个相同的转换函数。如果有两个隐式转换函数,只有函数名不同,则会导致错误。
  2. 不能多次转换:在一次转换过程中可以把A->B,B->C,但是不能直接从A->C。

基本代码

package imp

// 隐式转换规则
// 1. 无歧义规则。不能出现定义两个相同发转换函数

/**
 *
 * 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._