12.29

14 阅读6分钟
package imp

/*
 * 隐式转换函数:把double 转成 int
 */
object imp01 {
  implicit def double2int(d:Double):Int = {
    println("调用 double2int")
    d.toInt
  }

  def main(args: Array[String]): Unit = {
    var i:Int = 1;

    val d:Double = i // 把Int --> double 。隐式转换。把精度低的数据转成精度高的数据,这是可以的!!!

    i = 1.5 // 把double ---> int 。把高精度的转成低精度的的,错误!!!!
    printun(i)
  }
}

1. 定义了一个 “隐式转换函数”

implicit def double2int(d:Double):Int 的作用是:自动将Double类型的值转换为Int类型(转换时会调用d.toInt,同时打印 “调用 double2int”)。

2. 演示 “数值类型的隐式转换规则”

  • val d:Double = i:把Int(低精度)转成Double(高精度),这是Scala 默认支持的隐式转换,所以可以直接赋值。
  • i = 1.5:尝试把Double(高精度)转成Int(低精度),默认不允许直接转换,但因为定义了double2int这个隐式转换函数,Scala 会自动调用它完成转换。

3. 代码的实际执行效果

当运行main方法时:

  • 先定义Int类型的i=1,然后赋值给Double类型的d(自动隐式转换,无报错)。
  • 执行i = 1.5时,Scala 会自动调用double2int(1.5),将1.5转成Int类型的1,同时打印 “调用 double2int”。
  • 最后执行printun(i)(注:代码里这里应该是笔误,正确写法是println(i)),输出转换后的i值(即1)。
/*
 隐式函数
 1. implicit 修饰。
 2. 它会自动被调用。当系统检测到隐式转换失败的时候,去自动调用。
 3. 函数的名字不重要,重要的是它的输入参数的类型和返回值类型
 它的作用是:偷偷地把一种类型的数据转成另一种类型的数据!
 */
object imp01 {
  implicit def double2int(d:Double):Int = {
    println("调用 double2int")
    d.toInt
  }

  def main(args: Array[String]): Unit = {
    var i:Int = 1;

    val d:Double = i // 把int --> double 。隐式转换。把精度低的数据转成精度高的数据,这是可以的!!!

    i = 1.2 // 把double ---> int 。把高精度的转成低精度的的,错误!!!!
    i = 2.2
    i = 3.3
    
    println(i)
  }
}

1. 隐式函数的定义

scala

implicit def double2int(d: Double): Int = {
    println("调用 double2int")
    d.toInt
}
  • implicit 是 Scala 中的关键字,用来修饰 “隐式函数”。

  • 隐式函数的特点:在类型不匹配的时候,Scala 会自动调用它进行类型转换

  • 这个函数的功能:

    • 输入:一个 Double 类型的值。
    • 输出:将 Double 转成 Int(直接截断小数部分)。
    • 每次调用会打印 "调用 double2int"
  • 注意:隐式函数的名字(这里是 double2int)不重要,重要的是参数类型返回值类型


2. main 方法逻辑

scala

def main(args: Array[String]): Unit = {
    var i: Int = 1;

    val d: Double = i // 把 int --> double 。隐式转换。把精度低的数据转成精度高的数据,这是可以的!!!

    i = 1.2 // 把 double ---> int 。把高精度的转成低精度的的,错误!!!!
    i = 2.2
    i = 3.3
    
    println(i)
}

2.1 val d: Double = i

  • i 是 Int 类型,d 是 Double 类型。
  • 因为 Int 是低精度,Double 是高精度,Scala 默认允许这种自动转换(不会丢失信息)。
  • 这里没有调用我们自定义的 double2int,而是用了内置的隐式转换。

2.2 i = 1.2 / i = 2.2 / i = 3.3

  • i 是 Int 类型,右边是 Double 类型。

  • 默认情况下,Scala 不允许高精度类型直接赋值给低精度类型,因为可能会丢失信息。

  • 但是,因为我们定义了 implicit def double2int,Scala 会自动调用这个函数,把 Double 转成 Int

  • 每次赋值都会:

    1. 打印 "调用 double2int"
    2. 用 d.toInt 截断小数部分。

2.3 println(i)

  • 最终 i 的值是最后一次转换的结果:3.3 → 3

  • 输出:

    plaintext

    调用 double2int
    调用 double2int
    调用 double2int
    3
    

3. 运行结果示例

plaintext

调用 double2int
调用 double2int
调用 double2int
3

4. 总结

  • 隐式函数:在类型不匹配时自动调用,用来实现类型转换。
  • 隐式函数的参数类型返回值类型决定了它什么时候被调用。
  • 高精度转低精度,默认是禁止的,但可以用隐式函数绕过。
  • 隐式转换可以让代码更简洁,但也要小心使用,避免隐藏类型转换逻辑。
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")
  }
}

1. 隐式参数的定义

scala

implicit val defaultPassword: String = "88888888"
  • implicit 修饰一个 val(常量),表示它是一个隐式值
  • 隐式值的作用:当函数参数列表中有 implicit 参数,且调用时没有显式传值时,Scala 会在当前作用域中寻找匹配类型的隐式值来自动传入。
  • 这里定义了一个 String 类型的隐式值 defaultPassword,值为 "88888888"

2. 函数定义

scala

def reg(name: String)(implicit password: String = "123456"): Unit = {
    println(s"用户名:${name}, 密码: ${password}")
}
  • 这个函数有两个参数列表:

    1. 第一个参数列表(name: String),显式传入用户名。
    2. 第二个参数列表(implicit password: String = "123456")implicit 表示这是一个隐式参数。
  • 隐式参数可以有默认值,这里默认值是 "123456"

  • 如果调用时没有显式传值,Scala 会:

    1. 先找作用域中的隐式值(defaultPassword)。
    2. 如果找不到,再使用默认值。

3. main 方法调用

scala

def main(args: Array[String]): Unit = {
    reg("小花")
    reg("小明")("admin")
}

3.1 reg("小花")

  • 只传了第一个参数列表的 name"小花")。

  • 第二个参数列表没有传值,Scala 会:

    • 先找作用域中的隐式值:defaultPassword → "88888888"
    • 因为找到了,就使用这个值。
  • 输出:

    plaintext

    用户名:小花, 密码: 88888888
    

3.2 reg("小明")("admin")

  • 第一个参数列表传了 name"小明")。

  • 第二个参数列表显式传了 "admin",所以不会使用隐式值或默认值。

  • 输出:

    plaintext

    用户名:小明, 密码: admin
    

4. 运行结果示例

plaintext

用户名:小花, 密码: 88888888
用户名:小明, 密码: admin

5. 总结

  • 隐式参数:用 implicit 修饰的参数,可以在调用时省略,由 Scala 自动查找作用域中的隐式值填充。

  • 隐式值:用 implicit val 定义的常量,用于给隐式参数传值。

  • 默认值:隐式参数可以有默认值,如果找不到隐式值,就用默认值。

  • 隐式参数的匹配规则:类型匹配(这里是 String)。

  • 隐式参数常用于:

    • 配置信息(如默认密码、默认时区)。
    • 依赖注入。
    • 上下文信息传递。