Kotlin 物件:Object 與 Singleton
object 是 Kotlin 中一個非常獨特且強大的關鍵字。簡單來說,它同時完成了兩件事:
- 定義一個類別 (Class)
- 建立該類別的一個實例 (Instance)
這聽起來可能很抽象,但它主要解決了三個常見的程式設計情境:單例模式、靜態成員替代品、以及 匿名內部類別。
單例模式 (Singleton Pattern)
為什麼需要單例?
在開發應用程式時,有些物件我們只需要 一個全域唯一的實例,例如:
- 資料庫連線設定 (DatabaseConfig)
- 網路請求管理器 (NetworkManager)
- 系統設定 (AppSettings)
在 Java 中,要實作執行緒安全的 Singleton 很麻煩(需要寫 getInstance, synchronized, double-checked locking...)。
但在 Kotlin,你只需要把 class 改成 object,一切就搞定了。
如何使用
// 定義:使用 object 關鍵字
object DatabaseConfig {
val url = "jdbc:mysql://localhost:3306/db"
fun connect() {
println("Connecting to $url...")
}
}
fun main() {
// 使用:直接用「類別名稱」存取,不需要 (也不能) new
DatabaseConfig.connect()
println(DatabaseConfig.url)
}
Kotlin 的 Object Declaration 是 執行緒安全 (Thread-safe) 的,且採用 惰性初始化 (Lazy Initialization),也就是第一次被存取時才會真正建立物件。
伴生物件 (Companion Object)
這裡沒有 static 關鍵字!
許多從 Java 轉過來的開發者會問:「Kotlin 的 static 去哪了?」
答案是:Kotlin 沒有 static 關鍵字。
Kotlin 認為 static 會破壞物件導向的完整性。取而代之的是,如果你需要「不依賴實例就能呼叫」的方法或屬性(類別層級的成員),你應該使用 Companion Object。
如何使用
把它想成是這個類別的一個「隨身伴侶」物件。
class User {
// 這是「實例」成員:每個 User 都有自己的 name
var name: String = ""
// 這是「類別」成員:所有 User 共用一份
companion object {
// 全域常數
const val MAX_AGE = 100
// 工廠方法 (Factory Method)
fun createDefault(): User {
return User()
}
}
}
fun main() {
// 就像存取 static 成員一樣
println(User.MAX_AGE)
val user = User.createDefault()
}
物件表達式 (Object Expression)
臨時需要的物件
有時候我們只需要一個物件來實作某個介面(例如按鈕點擊監聽器),但不想為此特地去開一個新的 .kt 檔案定義一個 Class。
這時候就可以用 Object Expression,它對應到 Java 的 匿名內部類別 (Anonymous Inner Class)。
如何使用
語法是 object : 介面或類別 { ... }。
interface ClickListener {
fun onClick()
}
fun main() {
// "我需要一個實作 ClickListener 的物件,但我不想幫它取類別名稱"
val listener = object : ClickListener {
override fun onClick() {
println("Button clicked!")
}
}
listener.onClick()
}
臨時的資料容器
你甚至可以用它建立一個沒有型別的臨時物件來裝資料:
val tempPoint = object {
val x = 10
val y = 20
}
println("${tempPoint.x}, ${tempPoint.y}")
總結
- Object Declaration (
object Name):用來實作 單例模式 (Singleton),全域唯一。 - Companion Object (
companion object):放在 class 內部,用來取代 Java 的 static 重點 (常數、工廠方法)。 - Object Expression (
object : Type):用來建立 匿名物件,通常用於再一次性的介面實作。