scala的隐式转换基本使用

16 阅读3分钟

(一)什么是隐式转换

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

回顾如下代码:

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

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

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

var i:Int= 1.5;  // 这里会报错

(二)隐式函数

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

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

例如:把double 转成int

代码如下:

package imp

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

object imp01 {

  implicit  def double2int (d:Double):Int = {
    print("调用 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 = 2.2
    i = 3.3

    println(i)
  }

}

结果如下:

image.png

(二)隐式参数

如果一个参数的默认值会反复修改

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

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

package imp

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

      implicit password:String="123456"
 **/
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")
  }
}

结果如下

image.png

(四)转换规则

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

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

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

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

package imp
/*
隐式转换函数的规则
1. 无歧义规则。
不能写两个相同的转换函数!
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} 米"
  }

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

  implicit  def k2km (m: M):KM = { new KM (m.value/1000)}

  // 补充隐式函数,把BM -> M
  implicit  def bm2m (bm: BM):M = { new M (bm.value*100)}


  // 补充隐式函数,把BM -> M
  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)

  }
}

结果如下:

image.png