package lmp
/*
* 启动程序返回原理:把 Double 转换为 Int
*
* 启动前:
* 1. implicit 保护。
* 2. 它会自动调用。当系统遇到类型转换失败的时候,会自动调用。
* 3. 因执行任务不重要,需要修改它的输入数据的类型和返回值类型!
*
* 它的作用是:简单地把一种类型的数据转换为另一种类型的数据!
*/
object lmp01 {
// 隐式转换:Double -> Int
implicit def double2int(d: Double): Int = {
println("调用 double2int")
d.toInt
}
// 另一个隐式转换示例
implicit def double2int2(d: Double): Int = {
println("调用 double2int2")
d.toInt
}
def main(args: Array[String]): Unit = {
var i: Int = 1
// 隐式转换:Int -> Double
val d: Double = 1 // 这里发生了隐式转换:Int 被转换为 Double
// 这里会调用隐式转换:Double -> Int
i = 3.14.toInt // 显式转换,不会调用隐式转换
// 如果希望使用隐式转换,可以这样写:
// 但由于有多个隐式转换可用,可能会引起歧义
println(i) // 修正打印语句
}
}
Scala 隐式转换函数概要
一、基本概念
隐式转换函数是Scala中允许在类型不匹配时自动进行的类型转换机制。
基本语法:
scala
implicit def 转换函数名(参数: 源类型): 目标类型 = {
// 转换逻辑
}
二、主要用途
1. 类型增强
为现有类型添加新方法(Pimp My Library模式)
scala
implicit class RichString(str: String) {
def toCamelCase: String = {
str.split(" ").map(_.capitalize).mkString
}
}
// 使用
"hello world".toCamelCase // "HelloWorld"
2. 类型转换
自动进行类型间的转换
scala
implicit def intToDouble(i: Int): Double = i.toDouble
def process(d: Double): Unit = println(d)
process(42) // 自动调用 intToDouble
3. 接口适配
让不兼容的接口能够一起工作
scala
trait Animal {
def makeSound(): Unit
}
class Dog {
def bark(): Unit = println("Woof!")
}
implicit def dogToAnimal(dog: Dog): Animal = new Animal {
def makeSound(): Unit = dog.bark()
}
def makeAnimalSound(animal: Animal): Unit = animal.makeSound()
makeAnimalSound(new Dog()) // 自动转换
三、查找规则
Scala编译器按以下顺序查找隐式转换:
- 当前作用域
- 伴生对象
- 导入的隐式
scala
// 方式1:当前作用域
object Example {
implicit def a2b(a: A): B = ???
def test(): Unit = {
val b: B = new A() // 使用当前作用域的隐式
}
}
// 方式2:伴生对象
class A
object A {
implicit def a2b(a: A): B = new B
}
// 方式3:导入
import MyImplicits._
object MyImplicits {
implicit def stringToInt(s: String): Int = s.toInt
}
四、使用限制和最佳实践
限制:
- 避免歧义:同一作用域不能有多个相同的隐式转换
- 不递归:避免隐式转换的递归调用
- 明确性:转换应该是明显的、安全的
最佳实践:
scala
// 好的做法:使用隐式类进行类型增强
object RichWrapper {
implicit class RichInt(val i: Int) extends AnyVal {
def squared: Int = i * i
def isEven: Boolean = i % 2 == 0
}
}
// 使用
import RichWrapper._
println(5.squared) // 25
println(4.isEven) // true
// 好的做法:将隐式转换放在伴生对象中
case class Meter(value: Double)
object Meter {
implicit def meterToCm(m: Meter): Centimeter =
Centimeter(m.value * 100)
}