🚀 Scala Trait 从入门到真香 —— 一篇就够!

55 阅读1分钟

微信图片_20251014151033_10_20.jpg

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) ✔
┌─ 构造参数 ✘(用抽象类或依赖注入)
┌─ 线性化解决冲突 ✔