第7章:隐式与注解
一、导读
1.1 本章学习目标
第7章讲解 Scala 的高级特性:隐式参数、隐式转换、注解。
本章核心学习目标:
- 掌握隐式参数:自动传递上下文
- 理解隐式转换:自动类型转换
- 掌握注解:元编程基础
1.2 为什么本章如此重要
隐式是 Scala 最独特也最强大的特性。它支撑了类型类、DSL、上下文抽象等高级模式。
1.3 核心问题引导
隐式参数如何工作?
类型类(Type Class)模式是什么?
注解有什么用途?
二、核心概念详解
7.1 隐式参数
scala
// 隐式参数: 自动传递
case class Config(timeout: Int, retries: Int)
def connect(url: String)(implicit config: Config): Unit = {
println(s"Connecting to $url with timeout ${config.timeout}")
}
implicit val defaultConfig = Config(5000, 3)
connect("http://example.com") // 自动传入 defaultConfig
// 类型类模式
trait Show[A] {
def show(value: A): String
}
implicit val intShow: Show[Int] = (value: Int) => s"Int($value)"
implicit val stringShow: Show[String] = (value: String) => s"String($value)"
def display[A](value: A)(implicit s: Show[A]): String = s.show(value)
println(display(42)) // Int(42)
println(display("hello")) // String(hello)7.2 隐式转换
scala
// 隐式转换: 自动类型转换
class Fraction(val n: Int, val d: Int) {
override def toString = s"$n/$d"
def *(other: Fraction) = new Fraction(n * other.n, d * other.d)
}
object Fraction {
implicit def intToFraction(n: Int): Fraction = new Fraction(n, 1)
}
import Fraction._
val result = 3 * new Fraction(1, 2) // 3 自动转为 Fraction(3, 1)
println(result) // 3/2
// 隐式类: 扩展方法
implicit class StringOps(val s: String) extends AnyVal {
def shout: String = s.toUpperCase + "!"
def whisper: String = s.toLowerCase + "..."
}
println("hello".shout) // HELLO!
println("HELLO".whisper) // hello...7.3 注解
scala
import scala.annotation._
// 内置注解
@deprecated("Use newMethod instead", "1.0")
def oldMethod(): Unit = {}
@tailrec
def factorial(n: Int, acc: Int = 1): Int = {
if (n <= 1) acc
else factorial(n - 1, n * acc)
}
@volatile var running = true
// 自定义注解
import scala.annotation.StaticAnnotation
class description(text: String) extends StaticAnnotation
@description("This is a person class")
case class Person(name: String, age: Int)
// 编译时注解处理需要宏 (macro)三、实战案例
3.1 案例一:类型类实现 JSON 序列化
scala
// JSON 类型类
trait JsonWriter[A] {
def write(value: A): String
}
object JsonWriter {
def apply[A](implicit writer: JsonWriter[A]): JsonWriter[A] = writer
// 内置实例
implicit val stringWriter: JsonWriter[String] =
(value: String) => s""""$value""""
implicit val intWriter: JsonWriter[Int] =
(value: Int) => value.toString
implicit val boolWriter: JsonWriter[Boolean] =
(value: Boolean) => value.toString
implicit def listWriter[A](implicit w: JsonWriter[A]): JsonWriter[List[A]] =
(value: List[A]) => value.map(w.write).mkString("[", ",", "]")
implicit def mapWriter[A](implicit w: JsonWriter[A]): JsonWriter[Map[String, A]] =
(value: Map[String, A]) =>
value.map { case (k, v) => s""""$k":${w.write(v)}""" }
.mkString("{", ",", "}")
}
// 语法糖
implicit class JsonOps[A](val value: A) extends AnyVal {
def toJson(implicit writer: JsonWriter[A]): String = writer.write(value)
}
// 使用
println(42.toJson) // 42
println("hello".toJson) // "hello"
println(List(1, 2, 3).toJson) // [1,2,3]
println(Map("a" -> 1, "b" -> 2).toJson) // {"a":1,"b":2}四、本章小结
隐式参数自动传递上下文,支持类型类模式
隐式转换和隐式类扩展已有类型
注解提供元数据
五、思考与练习
隐式解析的优先级规则是什么?
如何避免隐式转换的歧义?