2012-03-15 88 views
70

我有一個非常簡單的問題 - 我們應該什麼時候在Scala中創建對象時應用新的關鍵字?是否當我們只嘗試實例化Java對象?斯卡拉「新」關鍵字

回答

112

,當你想引用一個class自己的構造函數使用new關鍵字:

class Foo { } 

val f = new Foo 

省略new,如果你指的是同伴對象的apply方法:

class Foo { } 
object Foo { 
    def apply() = new Foo 
} 

// Both of these are legal 
val f = Foo() 
val f2 = new Foo 

如果您犯了一個案例類:

case class Foo() 

斯卡拉暗中爲您創建一個同伴對象,把它變成這樣:

class Foo { } 
object Foo { 
    def apply() = new Foo 
} 

所以,你可以做

f = Foo() 

最後,請記住,沒有規定說的是,同伴apply 方法是在構造一個代理:

class Foo { } 
object Foo { 
    def apply() = 7 
} 

// These do different things 
> println(new Foo) 
[email protected] 
> println(Foo()) 
7 

而且,既然你提到的Java類:是 - Java類很少甲肝Ë 同伴與apply方法對象,所以你必須使用new和實際 類的構造函數。

+0

一個Java類絕不能有同伴對象。它可以有一個可以作爲Java類的工廠的對象 - 但這個對象不是它的伴侶對象。 – sschaef 2012-03-15 20:56:58

+0

@Antoras由於Scala類編譯爲Java字節碼,並且可以以編譯形式分發,Scala可以通過靜態MODULE $成員區分實際Scala協同程序和名爲Foo $的類之間的區別嗎? – Owen 2012-03-15 21:04:32

+1

我認爲scalac可以不同於此,因爲它指出伴侶對象必須與其伴侶類在同一個文件中聲明。由於伴侶「屬性」僅在Scala中存在,並且不在字節碼級別上,所以scalac必須檢查Scala代碼而不是Bytecode以確保遵循規範。 – sschaef 2012-03-15 21:20:08

13

是,當我們嘗試僅實例java對象?

不是。在scala中省略new有兩種一般情況。 隨着單一對象(被oftenly用於存儲靜態函數和類似於你可以在Java中看到一個什麼樣的工廠):

scala> object LonelyGuy { def mood = "sad" } 
defined module LonelyGuy 

scala> LonelyGuy 
res0: LonelyGuy.type = [email protected] 

scala> LonelyGuy.mood 
res4: java.lang.String = sad 

隨着case classes(實際上,下面有類+對象= companion模式,例如具有相同名稱的類和對象):

scala> case class Foo(bar: String) 
defined class Foo 


scala> Foo("baz") 
res2: Foo = Foo(baz) 

因此,當您使用簡單類時,規則與Java相同。

scala> class Foo(val bar: String) 
defined class Foo 

scala> new Foo("baz") 
res0: Foo = [email protected] 

// will be a error 
scala> Foo("baz") 
<console>:8: error: not found: value Foo 
     Foo("baz") 

獎金,還有Scala中的一個匿名類,可以構建這樣的:

scala> new { val bar = "baz" } 
res2: java.lang.Object{val bar: java.lang.String} = [email protected] 

scala> res2.bar 
res3: java.lang.String = baz