2013-04-24 90 views
7

使用new運算符定義對象與通過擴展類定義獨立對象之間的區別是什麼?斯卡拉 - 新的vs對象擴展

更具體而言,給定類型class GenericType { ... }val a = new GenericTypeobject a extends GenericType之間的區別是什麼?

+0

可能重複[val和對象在scala類內?](http://stackoverflow.com/questions/3448691/val-and-object-inside-a-scala-class) – Bergi 2016-05-25 04:00:25

回答

9

作爲一個實際問題,object聲明初始化爲相同的機制如在字節碼new。但是,有很多不同之處:

  • object作爲單例 - 每個屬於只有一個實例存在的類;
  • object被延遲初始化 - 它們只會在首次引用時被創建/初始化;
  • objectclass(或trait)的相同名稱是伴侶;
  • 定義在object上的方法在伴侶class上生成靜態轉發器;
  • object的成員可以訪問夥伴class的私人成員;
  • 當搜索implicits時,會查看相關*類或特徵的伴隨對象。

這些只是我能想到的蝙蝠權利的一些差異。可能還有其他人。

*什麼是「相關」類或性狀是一個更長的故事 - 查找堆棧溢出問題,如果你有興趣解釋它。如果您無法找到它們,請查看scala標記的維基。

4

對象定義(無論它是否擴展)意味着創建單例對象。

scala> class GenericType 
defined class GenericType 

scala> val a = new GenericType 
a: GenericType = [email protected] 

scala> val a = new GenericType 
a: GenericType = [email protected] 

scala> object genericObject extends GenericType 
defined module genericObject 

scala> val a = genericObject 
a: genericObject.type = [email protected] 

scala> val a = genericObject 
a: genericObject.type = [email protected] 
2

雖然object聲明與new表達式具有不同的語義,但本地object聲明適用於所有意圖,目的與具有相同名稱的lazy val相同。考慮:

class Foo(name: String) { 
    println(name+".new") 
    def doSomething(arg: Int) { 
    println(name+".doSomething("+arg+")") 
    } 
} 

def bar(x: => Foo) { 
    x.doSomething(1) 
    x.doSomething(2) 
} 

def test1() { 
    lazy val a = new Foo("a") 
    bar(a) 
} 

def test2() { 
    object b extends Foo("b") 
    bar(b) 
} 

test1限定a作爲懶惰VAL與Foo新實例初始化,而test2b定義爲一個object延伸Foo。 實質上,它們都會懶惰地創建一個Foo的新實例併爲其命名(a/b)。

,您可以嘗試在REPL並驗證它們都具有相同的行爲:由語言

scala> test1() 
a.new 
a.doSomething(1) 
a.doSomething(2) 

scala> test2() 
b.new 
b.doSomething(1) 
b.doSomething(2) 

所以儘管objectlazy val之間的語義差異(尤其是特殊處理的object的,如Daniel C.所述Sobral), a lazy val總是可以用相應的object代替(這不是一種非常好的做法),同樣也適用於屬於類/特徵成員的lazy val/object。 我能想到的主要實際區別是對象具有更具體的靜態類型:b類型爲b.type(它擴展了Foo),而a恰好類型爲Foo

+0

lazy val a:Foo =一個 – 2014-07-11 10:52:55