所謂伴生對象, 也是一個Scala中的單例對象, 使用object關鍵字修飾。 除此之外, 還有一個使用class關鍵字定義的同名類, 這個類和單例對象存在于同一個文件中, 這個類就叫做這個單例對象的伴生類, 相對來說, 這個單例對象叫做伴生類的伴生對象。 舉個栗子:
object Companion {
def show = println("I am a companion")
}
class Companion {
def shout = Companion.show
}(Companion.scala)
這個object就是伴生對象,這和java中的Singleton異曲同工,實際上伴生對象本身就是一個Singleton,不同的是,它有一個與之同名的類(這里的class Companion),二者可以相互訪問彼此的私有成員。
編譯一下:
scalac Companion.scala
同Singleton一樣,我們也得到了兩個文件:Companion.class和Companion$.class。我們還可以用javap查看反編譯的結果,其中,Companion$.class與之前的Singleton$.class幾近相同,這里就省略了。一起來看看Companion.class。
javap Companion
public class Companion extends java.lang.Object implements scala.ScalaObject{
public static final void show();
public Companion();
public void shout();
}
因為有了對應的class,object成了伴生對象。從結果可以看出,伴生對象和它對應的類在字節碼層面走到了一起(Companion類)。換句話說,在Scala里面的class和object在Java層面里面合二為一,class里面的成員成了實例成員,object成員成了static成員。我們已經知道,這里的static成員只是一個簡單的wrapper,封裝了實際的操作。
對應到反編譯的代碼上,我們看到了與object相關的那個static方法——show。因為要構建Companion的實例,所以,生成的代碼里有構造函數。此外,class Companion的實例方法shout在字節碼層面上也體現到了Companion類里。
至此,我們已經對伴生對象有了一個基本的了解。在Scala的層面上,我們把分屬于類和實例分開放置,從代碼的組織而言,會更加清晰。在實現層面上,它們都是按照對象處理的(分別用Companion$和Companion),從而達到了對象模型的統一。
文章列表