scala case类私有应用方法(repl bug?)

时间:2013-02-12 11:20:39

标签: scala constructor read-eval-print-loop case-class

Scala2.10.0 REPL中的

Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_13).
Type in expressions to have them evaluated. 
Type :help for more information.

scala> case class A private(i:Int)
defined class A

scala> A(1)
res0: A = A(1)

但如果编译

$ scala -version
Scala code runner version 2.10.0 -- Copyright 2002-2012, LAMP/EPFL
$ cat Main.scala 
package foo

case class A private (i:Int)

object Main extends App{
  println(A(1))
}

$ scalac Main.scala 
Main.scala:6: error: constructor A in class A cannot be accessed in object Main
  println(A(1))
          ^
one error found

A.apply(1)是编译错误。

这是Scala2.10.0 REPL错误吗?

FYI Scala2.9.2 REPL正在关注

Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_13).
Type in expressions to have them evaluated.
Type :help for more information.

scala> case class A private(i:Int)
defined class A

scala> A(1)
<console>:10: error: constructor A in class A cannot be accessed in object $iw
              A(1)
              ^

3 个答案:

答案 0 :(得分:2)

这看起来像是一个REPL错误。

请注意,构造函数被正确标记为private(换句话说,new A(1)无法按预期编译),只是工厂(A.apply)错误公开

答案 1 :(得分:-2)

我明白了......你认为在写A(1)时你正在调用构造函数。你不是。您正在调用自动​​生成的(公共)伴随对象及其公共apply方法中为您添加的工厂。

<强>附录

我反复错误的日子......

在2.10.0 REPL中:

scala> object REPL { case class CC1 private(i: Int); val cc1_1 = CC1(23) }
<console>:7: error: constructor CC1 in class CC1 cannot be accessed in object REPL
       object REPL { case class CC1 private(i: Int); val cc1_1 = CC1(23) }

答案 2 :(得分:-3)

REPL有一个巨大的语义差异w.r.t.普通的编译器。

考虑能够做到这一点意味着什么:

scala> val v1 = 23
v1: Int = 23

scala> val v1 = 42
v1: Int = 42

您可以在编译的Scala代码中执行此操作吗?当然不是,这将是一个禁止的双重定义。

REPL如何做到这一点?实际上,您输入的每一行都是逐步更嵌套的范围。重新定义的外观是实际的阴影。就好像你这样做了:

object REPL1 {
  val v1 = 23
  object REPL2 {
    val v1 = 42
    object REPL3 {
      // Next REPL line here...
    }
  }
}

那么,你如何得到同伴?在它们周围放置一个显式对象(或其他形成范围的构造)。请记住,没有空行。当你这样做时,REPL将停止接受给定“行”或“阻止”的输入。