【发布时间】:2012-04-01 10:15:57
【问题描述】:
我有一个非常简单的问题——在 Scala 中创建对象时,我们应该什么时候应用 new 关键字?当我们尝试仅实例化 Java 对象时?
【问题讨论】:
标签: scala new-operator keyword
我有一个非常简单的问题——在 Scala 中创建对象时,我们应该什么时候应用 new 关键字?当我们尝试仅实例化 Java 对象时?
【问题讨论】:
标签: scala new-operator keyword
当您想引用class 自己的构造函数时,请使用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 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 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 = 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
【讨论】:
当我们尝试仅实例化 Java 对象时?
对于 Scala 3(应该在 8 年后的 2020 年年中发布),based on Dotty:永远不会。
Scala 3 将删除“new”,如in this thread
Creator 应用程序允许使用简单的函数调用语法来创建实例 一个类,即使没有实现 apply 方法。
例子:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
Creator 应用程序概括了迄今为止仅为案例类提供的功能,但实现这一点的机制略有不同。
我们没有使用自动生成的 apply 方法,而是为函数调用f(args)添加了新的可能解释。
【讨论】: