scala隐式转换函数及隐式值

  • Post author:
  • Post category:其他




隐式转换

隐式函数基本介绍

隐式转换函数是以implicit关键字声明的带有单个参数的函数,这种函数将会自动调用,将值从一种类

型转换到另一种类型,使用隐式函数可以优雅的解决数据类型转换

隐式转换的注意事项和细节

1 隐式转换函数的函数名可以是任意的,隐式转换与函数名称无关,只与函数 签名(函数参数类型和

返回值类型)有关

2 隐式函数可以有多个(即:隐式函数列表),但是需要保证在当前环境下,只有一个隐式函数能被识

object ImplicitDemo01 {
  def main(args: Array[String]): Unit = {
    //编写一个隐式函数转成Double -> Int 转换
    //隐式函数应当在作用域才能生效
    implicit def f1(d:Double): Int ={ //底层生成f1$1
      d.toInt
    }
    implicit def f2(f:Float): Int ={
      f.toInt
    }
//     这里我们必须保证隐式函数的匹配只能是唯一的
//    implicit def f3(f1:Float): Int ={
//      f1.toInt
//    }
    val num: Int = 3.5  //底层编译f1$1(3.5)
    val num2: Int = 4.5f
    println("num=" + num)
  }
}



隐式转换丰富类库功能

基本介绍

如果需要为一个类增加一个方法,可以通过隐式转换来实现.(动态增加功能)比如想为MySQL类增加一个delete方法

分析解决方案

在当前程序中,如果想要给MySQL类增加功能是非常简单的,但是在实际项目中,如果想要增

加新的功能就会需要改变源代码,这是很难受的,而且违背了软件开发的OCP开发原则(闭合原则

open close priceple)在这种情况下,可以通过隐式转换函数给类动态添加功能

object ImplicitDemo02 {
  def main(args: Array[String]): Unit = {
    //编写一个隐式函数,丰富mysql功能
    implicit def addDelete(msql:MySQL): DB = {
      new DB
    }
    // 创建mysql对象
    val mySQL = new MySQL
    mySQL.insert()
    mySQL.delete()  //分析  addDelete$1(mySQL).delete()
    mySQL.update()
  }
}
class MySQL{
  def insert(): Unit ={
    println("insert")
  }
}
class DB{
  def delete(): Unit ={
    println("delete")
  }
  def update(){
    println("update")
  }
}



隐式值

基本介绍

隐式值也叫隐式变量,将某个形参变量标记为implicit,所以编译器会在方法省略隐式参数的情况下去

搜索作用域内的隐式值作为缺省参数

示例:

object ImplicitValDemo03 {
  def main(args: Array[String]): Unit = {
    implicit val str1: String = "jack**"  //这个就是隐式值

    // implicit name: String  :name就是隐式参数
    def hello(implicit name: String): Unit ={
      println(name + "hello")
    }
    hello  //底层hello$1(str1)  使用隐式值不要带()
  }
}

案例1

隐式匹配具有唯一性

示例:

object ImplicitVal02 {
  def main(args: Array[String]): Unit = {
    implicit val name: String = "Scala"
    implicit val name1: String = "World"

    // 隐式参数
    def hello(implicit content: String = "jack"): Unit ={
      println("Hello" + content)
    }//调用hello
    hello
  }
}

这个时候程序会报错,显示错误:

在这里插入图片描述

程序会显示模糊的隐式值这样一个错误,原因是因为程序中两个隐式变量name和name1的类型

都是String类型,编译器去匹配时无法识别到底是哪一个,因此会报错。这个时候注销一个,程序就

会正常运行,这也再次证明了隐式匹配具有唯一性。

示例:

在这里插入图片描述

案例2

	当同时有implicit值和默认值,implicit优先级高

示例:

object ImplicitVal02 {
  def main(args: Array[String]): Unit = {
    implicit val name: String = "Scala"
    //当同时有implicit值和默认值,implicit优先级高
    def hello2(implicit content: String = "jack"): Unit ={
      println("Hello2" + content)
    }//调用hello2
    hello2
  }
}

运行结果:

在这里插入图片描述

案例3

	当一个隐式参数匹配不到隐式值,仍然会使用默认值

示例:

在这里插入图片描述

案例4

	当程序中隐式参数content没给默认值时,这个时候程序会报错,原因是当调用函数时,它首先会去找隐式值,发

现上面有一个,但是是个Int类型的不能匹配,于是隐式值是匹配不到的,默认值又没给,同时还不传

值,因此就报错了。但当三者都存在的时候,即既有隐式值,又有默认值,还传了值,那这个时候传

的值优先级最高,然后是隐式值,最后是默认值。

示例:

在这里插入图片描述

小结:

1 当在程序中,同时有隐式值,默认值,传值

2 编译器的优先级为 传值 > 隐式值 > 默认值

3 在隐式值匹配时,不能有二义性(即不能匹配多个)

4 如果三个(隐式值,默认值,传值) 一个都没有,就会报错



版权声明:本文为one111a原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。