【问题标题】:"new" keyword in ScalaScala中的“新”关键字
【发布时间】:2012-04-01 10:15:57
【问题描述】:

我有一个非常简单的问题——在 Scala 中创建对象时,我们应该什么时候应用 new 关键字?当我们尝试仅实例化 Java 对象时?

【问题讨论】:

    标签: scala new-operator keyword


    【解决方案1】:

    当您想引用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 类永远不能有伴生对象。它可以有一个对象,该对象可以作为 Java 类的工厂 - 但该对象不是它的伴生对象。
    • @Antoras 由于 Scala 类编译为 Java 字节码,并且可以以编译形式分发,Scala 能否区分实际的 Scala 伴侣和具有静态 MODULE$ 成员的名为 Foo$ 的类?
    • 我认为 scalac 可能会有所不同,因为它规定一个伴生对象必须在与其伴生类相同的文件中声明。因为伴随的“属性”只存在于 Scala 而不是字节码级 scalac 必须检查 Scala 代码而不是字节码以确保遵循规范。
    • 有没有在 Scala 中不使用 new 关键字的 Java 类示例?
    • 此外,伴生对象上的方法也可以通过类上的静态方法访问,并且以后为您定义“伴生”的 java 类永远不会发生这种情况。
    【解决方案2】:

    当我们尝试仅实例化 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
    

    【讨论】:

    • 你还好吗?
    【解决方案3】:

    当我们尝试仅实例化 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) 添加了新的可能解释。

    【讨论】:

      猜你喜欢
      • 2015-09-10
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 2010-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      相关资源
      最近更新 更多