隐式转换 #
一、隐式转换概述 #
1.1 什么是隐式转换 #
隐式转换允许自动将一种类型转换为另一种类型,常用于:
- 扩展现有类的功能
- 类型适配
- 提供默认值
1.2 Scala 2 vs Scala 3 #
| Scala 2 | Scala 3 |
|---|---|
| implicit | given / using |
| implicit class | extension |
| implicit def | given Conversion |
二、隐式类(Scala 2) #
2.1 定义隐式类 #
scala
implicit class StringExtensions(val s: String) extends AnyVal:
def greet: String = s"Hello, $s!"
def shout: String = s.toUpperCase + "!"
def repeat(n: Int): String = s * n
"Scala".greet
"hello".shout
"ab".repeat(3)
2.2 隐式类规则 #
- 必须有且仅有一个参数
- 不能是顶层类
- 不能是 case class
2.3 扩展方法 #
scala
implicit class IntExtensions(val n: Int) extends AnyVal:
def times(action: => Unit): Unit = (1 to n).foreach(_ => action)
def isEven: Boolean = n % 2 == 0
def isOdd: Boolean = n % 2 != 0
5.times(println("Hello"))
42.isEven
三、Extension 方法(Scala 3) #
3.1 定义扩展方法 #
scala
extension (s: String)
def greet: String = s"Hello, $s!"
def shout: String = s.toUpperCase + "!"
def repeat(n: Int): String = s * n
"Scala".greet
"hello".shout
"ab".repeat(3)
3.2 泛型扩展方法 #
scala
extension [T](list: List[T])
def second: Option[T] = list.drop(1).headOption
def third: Option[T] = list.drop(2).headOption
def takeWhileWithIndex(p: (T, Int) => Boolean): List[T] =
list.zipWithIndex.takeWhile(p.tupled).map(_._1)
List(1, 2, 3, 4, 5).second
List("a", "b", "c").third
3.3 扩展方法组织 #
scala
object StringExtensions:
extension (s: String)
def greet: String = s"Hello, $s!"
def shout: String = s.toUpperCase + "!"
import StringExtensions.*
"Scala".greet
四、Given 和 Using(Scala 3) #
4.1 定义 Given #
scala
trait Show[T]:
def show(value: T): String
given Show[Int] with
def show(value: Int): String = value.toString
given Show[String] with
def show(value: String): String = value
given Show[Boolean] with
def show(value: Boolean): String = value.toString
4.2 使用 Given #
scala
def printShow[T](value: T)(using show: Show[T]): Unit =
println(show.show(value))
printShow(42)
printShow("hello")
printShow(true)
4.3 匿名 Given #
scala
given ordering: Ordering[Person] = Ordering.by(_.age)
given Show[Int] = _.toString
4.4 Given 导入 #
scala
object ShowInstances:
given Show[Int] with
def show(value: Int): String = value.toString
given Show[String] with
def show(value: String): String = value
import ShowInstances.given
printShow(42)
五、隐式转换函数 #
5.1 Scala 2 隐式转换 #
scala
implicit def intToString(n: Int): String = n.toString
val s: String = 42
5.2 Scala 3 Conversion #
scala
given Conversion[Int, String] = _.toString
val s: String = 42
5.3 自定义转换 #
scala
case class Meter(value: Double)
case class Kilometer(value: Double)
given Conversion[Meter, Kilometer] = m => Kilometer(m.value / 1000)
given Conversion[Kilometer, Meter] = km => Meter(km.value * 1000)
val m = Meter(1000)
val km: Kilometer = m
println(km)
六、隐式参数 #
6.1 定义隐式参数 #
scala
trait Config:
def host: String
def port: Int
def connect()(using config: Config): Connection =
???
given Config with
def host: String = "localhost"
def port: Int = 8080
connect()
6.2 多个隐式参数 #
scala
trait Logger:
def log(message: String): Unit
trait Database:
def query(sql: String): Result
def processData()(using logger: Logger, db: Database): Unit =
logger.log("Processing data")
db.query("SELECT * FROM data")
given Logger with
def log(message: String): Unit = println(s"[LOG] $message")
given Database with
def query(sql: String): Result = ???
processData()
6.3 隐式参数默认值 #
scala
def greet(name: String)(using greeting: String = "Hello"): String =
s"$greeting, $name!"
greet("Alice")
greet("Bob")(using "Hi")
七、类型类模式 #
7.1 定义类型类 #
scala
trait JsonWriter[T]:
def write(value: T): String
object JsonWriter:
given JsonWriter[Int] with
def write(value: Int): String = value.toString
given JsonWriter[String] with
def write(value: String): String = s""""$value""""
given JsonWriter[Boolean] with
def write(value: Boolean): String = value.toString
given [T](using writer: JsonWriter[T]): JsonWriter[List[T]] with
def write(value: List[T]): String =
value.map(writer.write).mkString("[", ", ", "]")
given [K, V](using keyWriter: JsonWriter[K], valueWriter: JsonWriter[V]): JsonWriter[Map[K, V]] with
def write(value: Map[K, V]): String =
value.map { case (k, v) => s"${keyWriter.write(k)}: ${valueWriter.write(v)}" }
.mkString("{", ", ", "}")
7.2 使用类型类 #
scala
def toJson[T](value: T)(using writer: JsonWriter[T]): String =
writer.write(value)
import JsonWriter.given
toJson(42)
toJson("hello")
toJson(List(1, 2, 3))
toJson(Map("a" -> 1, "b" -> 2))
7.3 类型类扩展 #
scala
case class Person(name: String, age: Int)
object Person:
given JsonWriter[Person] with
def write(value: Person): String =
s"""{"name": "${value.name}", "age": ${value.age}}"""
toJson(Person("Alice", 25))
八、隐式解析规则 #
8.1 查找顺序 #
- 当前作用域
- 导入的隐式值
- 伴生对象中的隐式值
- 外部作用域
8.2 隐式作用域 #
scala
case class Person(name: String, age: Int)
object Person:
given Show[Person] with
def show(value: Person): String = s"${value.name} (${value.age})"
def printShow[T](value: T)(using show: Show[T]): Unit =
println(show.show(value))
printShow(Person("Alice", 25))
九、最佳实践 #
9.1 使用 extension 替代 implicit class #
scala
extension (s: String)
def greet: String = s"Hello, $s!"
9.2 使用 given/using 替代 implicit #
scala
given Show[Int] = _.toString
def show[T](value: T)(using s: Show[T]): String = s.show(value)
9.3 类型类放在伴生对象中 #
scala
case class Person(name: String, age: Int)
object Person:
given Show[Person] with
def show(value: Person): String = s"${value.name} (${value.age})"
9.4 避免隐式转换滥用 #
scala
given Conversion[String, Int] = _.length
val n: Int = "hello"
十、总结 #
Scala 3 隐式语法 #
| 概念 | 语法 |
|---|---|
| 定义隐式值 | given Name: Type = value |
| 定义隐式参数 | using param: Type |
| 扩展方法 | extension (x: T) def method |
| 类型转换 | given Conversion[A, B] |
类型类模式 #
| 组件 | 说明 |
|---|---|
| Trait | 定义行为接口 |
| Given | 提供具体实现 |
| Using | 使用隐式值 |
下一步,让我们学习 上下文界定!
最后更新:2026-03-27