scala的隐式转换基本使用(一)

22 阅读2分钟

隐式转换的定义

隐式转换是指:scala自动把一种类型转成另一种类型的过程。

隐式函数

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

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

语法格式:

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

注意点:

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

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

基本代码:

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

// 注意:

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

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


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

  def main(args: Array[String]): Unit = {
    // 隐式转换
    var i:Int=1;
    var d:Double=1.1;

    d=i // 把int → double类型

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


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

}

隐式参数

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

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

基本代码:

package imp

// 在写代码的过程中,有一个原则:尽量不要修改之前的代码
// 隐式参数
//在开发过程中,如果预判一个参数未来将会变动,就可以把它设置为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="108"
 * }
 */



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

  }

}