2012-03-15 82 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