1️⃣ 什么是 Trait?🤔
Trait ≈ 接口 + 抽象类 + 装饰器 的混合体:
- 可以 定义抽象成员(待实现)
- 可以 给出默认实现( mixin )
- 可以 多重混入(告别 Java 单继承)
- 无构造参数(跟抽象类最大的区别)
一句话:Trait 是 Scala 的 “乐高积木”,哪里需要拼哪里!
2️⃣ 最小可运行示例 🎯
// 1. 定义一个「会打招呼」的特质
trait Greeting {
def name: String // 抽象字段
def greet(): Unit = // 默认实现
println(s"Hello, $name!")
}
// 2. 定义一个「会告别」的特质
trait Farewell {
def bye(): Unit = println("See you~")
}
// 3. 多重混入
class Person(val name: String) extends Greeting with Farewall
object Demo extends App {
val p = new Person("掘金酱")
p.greet() // Hello, 掘金酱!
p.bye() // See you~
}
3️⃣ 抽象 vs 具体 —— 一目了然 🎨
| 成员类型 | 语法示例 | 是否必须实现 |
|---|---|---|
| 抽象方法 | def foo: Int | ✅ 子类必须实现 |
| 具体方法 | def bar = 42 | ❌ 可直接用 |
| 抽象字段 | val x: Int | ✅ 子类必须补 |
| 具体字段 | val y = 10 | ❌ 已初始化 |
4️⃣ 叠加冲突?用 super + linearization !🧩
trait A { def msg: String = "A" }
trait B extends A { override def msg = "B -> " + super.msg }
trait C extends A { override def msg = "C -> " + super.msg }
class D extends B with C { // 线性化:D -> C -> B -> A
override def msg = "D -> " + super.msg
}
println(new D().msg) // D -> C -> B -> A
口诀:从右到左,一路 super 串糖葫芦!
5️⃣ 自带类型约束 —— 让错误在编译期爆炸 💥
trait Comparable[T] {
def compare(that: T): Int
def < (that: T): Boolean = compare(that) < 0
}
case class Money(amount: Int) extends Comparable[Money] {
override def compare(that: Money) = this.amount - that.amount
}
Money(1) < Money(2) // true
6️⃣ 实战:蛋糕模式(Cake Pattern)🍰
// 1. 组件 trait
trait UserRepo { def find(id: Long): String }
trait MailService { def send(to: String): Unit }
// 2. 依赖声明
trait UserService { self: UserRepo with MailService =>
def register(id: Long): Unit = {
val user = find(id)
send(user)
}
}
// 3. 组装「蛋糕」
object ComponentRegistry
extends UserService
with UserRepo
with MailService {
override def find(id: Long) = s"user$id"
override def send(to: String) = println(s"Mail to $to")
}
ComponentRegistry.register(666L) // Mail to user666
7️⃣ Trait 构造顺序 🔧
trait T1 { println("T1") }
trait T2 { println("T2") }
class C extends T1 with T2 { println("C") }
new C()
// 打印顺序:T1 → T2 → C
8️⃣ 总结:一张图背下来 📌
Trait 能力清单
┌─ 抽象/具体 方法 ✔
┌─ 抽象/具体 字段 ✔
┌─ 多重混入(mixin) ✔
┌─ 构造参数 ✘(用抽象类或依赖注入)
┌─ 线性化解决冲突 ✔