Scala中的“ new”关键字


93

我有一个非常简单的问题-在Scala中创建对象时,何时应应用new关键字?当我们尝试仅实例化Java对象时,是这样吗?

Answers:


144

new当您要引用class自己的构造函数时,请使用关键字:

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()

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和实际类的构造函数。


1
Java类永远不能有一个伴随对象。它可以具有一个可用作Java类的Factory的对象-但此对象不是其伴随对象。
kiritsuku 2012年

@Antoras由于Scala类可以编译为Java字节码,并且可以以编译形式分发,因此Scala能否区分实际的Scala伴侣和具有静态MODULE $成员的名为Foo $的类之间的区别?
欧文

1
我认为scalac可以有所不同,因为它规定必须将同伴对象与其同伴类声明在同一文件中。因为伴随的“属性”仅存在于Scala中,而不存在于Bytecode级scalac上,因此必须检查Scala代码而不是Bytecode,以确保遵循规范。
kiritsuku 2012年

1
在Scala中不使用new关键字的Java类的示例吗?
Bober02年

同样,也可以通过类上的静态方法来访问伴随对象上的方法,而对于以后要为其定义“伴侣”的java类,则永远不会发生这种情况。
drexin 2012年

16

当我们尝试仅实例化Java对象时,是这样吗?

一点也不。当您new在scala中省略时,通常有两种情况。使用单例对象(通常用于存储静态函数并作为一种工厂,类似于您在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

对于案例类(实际上,在下面是类+对象= 伴随模式,例如,具有相同名称的类和对象):

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

1
你知道那里芽吗?
雅各布·B

0

当我们尝试仅实例化Java对象时,是这样吗?

使用基于Dotty的 Scala 3(应于2020年中发布,八年后):永远不会。

Scala 3将在该线程中删除“ new

即使没有实现apply方法,Creator应用程序也允许使用简单的函数调用语法来创建类的实例。

例:

class StringBuilder(s: String) {
   def this() = this(s)
}

StringBuilder("abc")  // same as new StringBuilder("abc")
StringBuilder()       // same as new StringBuilder()

Creator应用程序概括了迄今为止仅为案例类提供的功能,但是实现该功能的机制略有不同。
代替自动生成的apply方法,我们向函数调用添加了新的可能的解释f(args)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.