Scala 的套件、匯入與存取修飾符機制提供了超越 Java 的封裝靈活性。本文系統整理這些特性,幫助 Java 開發者快速掌握 Scala 的模組化與存取控制精髓。
Scala 支援兩種套件宣告方式:
// 巢狀風格
package com {
package tedneward {
package scala {
package demonstration {
object App { ... }
}
}
}
}
// 等價的簡潔寫法
package com.tedneward.scala.demonstration {
object App { ... }
}
兩者編譯產出相同的類別結構,開發者可依團隊習慣選擇。
Scala 的 import 具有幾大亮點:
object App {
import java.math.BigInteger // 僅限 App 內部可見
def factorial(arg: BigInteger): BigInteger = ...
}
import java.math.BigInteger
import BigInteger._ // 將 ZERO、ONE 等靜態欄位引入當前作用域
// 甚至可合併為單行
import java.math.BigInteger, BigInteger._
object BizarroMath {
def bizplus(a: Int, b: Int) = a - b
def bizminus(a: Int, b: Int) = a + b
...
}
import com.tedneward.scala.mathfun.BizarroMath._
// 之後可直接呼叫 bizplus(2,2)
Scala 重新定義了存取層級:
| 修飾符 | 說明 |
|---|---|
public(預設) | 無關鍵字,預設為公有 |
private | 僅限定義該成員的類別/物件內部可見 |
protected | 僅子類別可見(比 Java 更嚴格,同套件不可見) |
private[套件名] | 限定至指定套件層級可見 |
private[this] | 物件私有,同類別的其他實例也不可見 |
package com.tedneward.scala.mathfun {
object BizarroMath {
private[mathfun] def bizexp(a: Int, b: Int) = 0
// mathfun 套件內所有成員可存取,外部不可存取
}
}
這種「限定私有」機制極大增強了封裝彈性,可精確控制模組間的可見性。
受限於 JVM 位元組碼模型,Scala 的精細存取控制編譯後會映射為 public。若 Scala 程式碼需供 Java 呼叫,建議堅持使用傳統 private/public,並以 javap 驗證實際可見性。
Scala 為 () 運算子保留特殊語法糖:對物件套用 () 時,實際呼叫其 apply() 方法。這使任何類別都能成為「函子」(functor):
class Functor {
def apply() = "Doing something without arguments"
def apply(i: Int) = if (i == 0) "Done" else "Applying... " + apply(i - 1)
}
val f = new Functor
f() // 呼叫 apply()
f(3) // 呼叫 apply(3)
標準庫中的 Function1、Function2 等皆實作 apply,匿名函數本質即是這些類別的實例。開發者可自訂 apply 實現策略模式,無需共同基類:
class GoodAdder { def apply(lhs: Int, rhs: Int) = lhs + rhs }
class BadAdder(inflate: Int) { def apply(lhs: Int, rhs: Int) = lhs + rhs * inflate }
val calc = new GoodAdder
calc(2, 2) // 4
val enron = new BadAdder(50)
enron(2, 2) // 102
Scala 的套件巢狀作用域、靈活匯入、限定存取修飾符與 apply 機制,共同構建出比 Java 更精細、更具表達力的封裝體系。這些特性不僅支援大型系統的模組化,也為 DSL 設計提供了語法基礎。