2019-04-22
關鍵字:Scala 伴生對象的作用
關於 Scala 伴生對象,比教材更詳細的解釋。
什么是伴生對象?
教材中關於伴生對象的解釋是:實現類似 Java 中那種既有實例成員又有靜態成員的類的功能。
為什么上面說它是一種 “功能” 呢?因為要想實現像 Java 中那樣的類,光靠一個 Scala 類可不行。在 Scala 中,我們必須:
1. 定義一個 class 並在這里面實現所有的實例成員。
2. 添加一個 object ,這個 object 要與上面的 class 同名,然后在這里面實現所有的靜態成員。
3. 定義的 class 與 object 必須在同一個文件內。
滿足了上面 3 條要求以后,就可以實現類似 Java 中一個類既存在實例成員又存在靜態成員的功能了。然后我們通常把第 2 步添加的 object 稱為 “伴生對象” 。轉化成代碼,就像下面這樣
class CompanionDemo { println("new CompanionDemo clz") def init(): Unit = { // our codes... } } object CompanionDemo { println("new CompanionDemo object") def prt(): Unit = { // our codes... } }
伴生對象有什么特點?
毫無疑問,伴生對象這種存在最大的特點就是可以實現類似 Java 中那樣,在同一個類里既有實例成員又有靜態成員的功能。
另一個特點就是 class CompanionDemo 和 object CompanionDemo 雖然分開兩處定義,但卻可以訪問對方的 private 變量及方法。訪問私有屬性的一個小示例如下

class CompanionDemo { private var clzi = 0 def init(): Unit = { println("variable in clz:" + clzi) println("variable from object:" + CompanionDemo.obji) CompanionDemo.access(this) } } object CompanionDemo { private var obji = 1 def access(clz: CompanionDemo): Unit = { println("variable in object:" + obji) println("variable from clz:" + clz.clzi) } }
並通過如下代碼來訪問伴生對象
object cpDemp { def main(args: Array[String]){ val cd = new CompanionDemo() cd.init() } }
執行結果如下

variable in clz:0 variable from object:1 variable in object:1 variable from clz:0
伴生對象中要想訪問對方的私有屬性,需要注意以下 2 點
1. class 中要訪問 object 中的私有屬性,直接以 object 名來 “點” 相應的變量或方法即可,可以參考上面例子;
2. object 中要訪問 class 中的私有屬性,必須要通過 class 的對象引用來 “點” 相應變量或方法,可以參考上面例子。
伴生對象的意義是什么?
Scala 中沒有 static 關鍵字,而 Scala 又運行與 JVM 之上,與 Java 類庫完全兼容的編程語言,同時類中擁有靜態屬性又是如此的有必要,因此推出這個伴生對象機制就顯得很有必要了。所以第 1 個意義就是為了彌補類中不能定義 static 屬性的缺陷。
那我們知道,在 Java 中靜態屬性是屬於類的,在整個 JVM 中只開辟一塊內存空間,這種設定使得靜態屬性可以很節省內存資源,不用擔心像實例屬性那樣有內存溢出的風險。在 Scala 中伴生對象本質上也是生成靜態屬性,所以這第 2 個意義就是節省內存資源。
既然靜態屬性在整個 JVM 中僅開辟一塊內存空間,那就說明我們可以在所有實例當中共享這塊內存里面的信息,所以第 3 個意義就是資源共享。