Scala中的隐式函数、隐式参数

27 阅读2分钟

隐式函数定义:

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

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

!!注意:

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

示例代码:

/*
隐式转换函数:把double转成int

隐式函数
1.implicit 修饰
2.它会自动被调用。当系统检测到隐式转换失败的时候,去自动调用
3.函数的名字不重要,重要的是它的输入数据的类型和返回值类型

作用:偷偷地把一种类型的数据转换成另一种类型的数据!
 */
object day01 {
   implicit  def double2int(d:Double):Int={
     println("调用 double2int")
     d.toInt
   }
  def main(args: Array[String]): Unit = {
     var i:Int=1
     val d:Double=i
     i=1.2
     i=2.2
     i=3.3
     println(i)
  }
}

隐式参数

示例代码1:

/*
隐式参数:如果在写函数的参数的时候,预计某个参数的默认值可能会被修改。可以设置隐式参数
implicit password:String="123456"--->隐式参数
 */
object day02 {
  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")
  }
}

示例代码2:

/*
隐式参数:如果在写函数的参数的时候,预计某个参数的默认值可能会被修改。可以设置隐式参数
implicit password:String="123456"--->隐式参数
 */
object day02 {
  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)}

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

转换规则

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

如下的代码会导致编译错误

implicit def fun1(a:Int):String = a.toString  
  implicit def fun2(b:Int):String = b.toString

错误的原因是这里有两个转换函数,导致代码在编译时,无法确定使用哪一个。

规则2:不能多次转换:在一次转换过程中可以把A->B,B->C,但是不能直接从A->C。来通过具体的代码来说明。

package pub  
object Test {  
  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 bm2km(bm:BM):KM = new KM(bm.value / 10)  
  implicit def m2bm(m:M):BM = new BM(m.value / 100)  
  
  def main(args: Array[String]): Unit = {  
    val mi = new M(1230)  
    val baimi1:BM = mi  
    println(baimi1)  
      
    val baimi = new BM(123)  
    val c:KM = baimi;  
    println(c)  
    val c1:KM = mi  
  }  
}