我有一个非常简单的问题 - 在Scala中创建对象时,何时应该使用new关键字?只有在实例化Java对象时才需要吗?
在想要引用一个类自己的构造函数时,使用new
关键字:
class Foo { }
val f = new Foo
如果你想引用伴生对象的 apply
方法,则可以省略 new
:
class Foo { }
object Foo {
def apply() = new Foo
}
// Both of these are legal
val f = Foo()
val f2 = new Foo
如果您创建了一个 case class:case class Foo()
Scala会为你偷偷地创建一个伴生对象,这会变成这样:
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)
test@5c79cc94
> println(Foo())
7
而且,既然你提到了Java类:是的 - Java类很少有伴生对象,其中包含一个apply
方法,因此您必须使用new
和实际类的构造函数。
这只发生在我们尝试实例化Java对象时吗?
完全不是。在Scala中有两种常见的情况可以省略new
关键字。
对于单例对象(通常用于存储静态函数并作为工厂类似于Java中的用法):
scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy
scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$@3449a8
scala> LonelyGuy.mood
res4: java.lang.String = sad
通过使用case类(实际上,在底层是类+对象= 伴生模式,例如使用相同名称的类和对象):
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 = Foo@2ad6a0
// 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} = $anon$1@10ee5b8
scala> res2.bar
res3: java.lang.String = baz
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
f(args)
添加了一种新的可能解释。