7

在 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 错误吗?

仅供参考 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)
              ^
4

3 回答 3

2

这绝对看起来像一个 REPL 错误。

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

于 2013-02-12T12:47:15.697 回答
-2

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

附录

我的日子一再犯错……</p>

在 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) }
于 2013-02-12T16:22:14.530 回答
-3

REPL 与普通编译器有一个巨大的语义差异。

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

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 将停止接受给定“行”或“块”的输入。

于 2013-02-12T14:53:55.057 回答