Scala 不僅為 JVM 帶來函數式編程,更提供現代物件導向設計視角。本文探討 特質 如何讓物件構建更簡單、更強大——它介於 Java 介面與 C++ 多重繼承之間,兼具兩者優點卻避開其缺陷。
PropertyChangeSupport)。// Java:每個 POJO 重複 30+ 行樣板代碼
public class Person {
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public void setFirstName(String v) {
String old = firstName; firstName = v;
pcs.firePropertyChange("firstName", old, v);
}
// add/remove listener 委派給 pcs...
}
特質可:
with Trait),一個類可混入多個特質this 給特質欄位)trait BoundPropertyBean {
import java.beans._
val pcs = new PropertyChangeSupport(this) // this 遲綁定到混入類
def addPropertyChangeListener(l: PropertyChangeListener) = pcs.addPropertyChangeListener(l)
def removePropertyChangeListener(l: PropertyChangeListener) = pcs.removePropertyChangeListener(l)
def firePropertyChange(name: String, oldVal: Any, newVal: Any) =
pcs.firePropertyChange(new PropertyChangeEvent(this, name, oldVal, newVal))
}
class Person(var firstName: String, var lastName: String, var age: Int)
extends Object with BoundPropertyBean {
override def toString = s"[Person: firstName=$firstName, lastName=$lastName, age=$age]"
// 只需覆寫 setter 觸發事件
def setFirstName(v: String) = { val o = firstName; firstName = v; firePropertyChange("firstName", o, v) }
def setLastName(v: String) = { val o = lastName; lastName = v; firePropertyChange("lastName", o, v) }
def setAge(v: Int) = { val o = age; age = v; firePropertyChange("age", o, v) }
}
javap -private 可見 private final PropertyChangeSupport pcs 直接存在於 Person 類中super、存取混入類私有欄位,編譯器負責線性化排序Application:提供 main 入口,支援 -Dscala.time 計時Ordered[A]:只需實作 compare(that: A): Int,自動獲得 < > <= >= compareTo 等關係運算子純方法簽名的特質編譯為標準 Java 介面(POJI),Java 代碼可直接實現/調用:
// Scala
trait Student { def getFirstName: String; def teach(subject: String) }
object StudentFactory {
class StudentImpl(var first: String, var last: String, var subject: String) extends Student { ... }
def getStudent(fn: String, ln: String) = new StudentImpl(fn, ln, "Scala")
}
// Java
Student s = StudentFactory.getStudent("Neo", "Anderson");
s.teach("Kung fu"); // 輸出 "I know Kung fu"
特質是 Scala 解決「行為複用 vs 型別階層」張力的關鍵創新。它讓我們以組合方式構建物件,避免繼承層次膨脹,同時保持與 Java 生態無縫互操作。下期將探討 Scala 泛型與解析器組合子。