2013-02-12 10 views
7

in Scala2.10.0 REPLscala Fall Klasse private Methode anwenden (ers Bug?)

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) 

Aber wenn kompilieren

$ 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) Fehler kompilieren.

ist dieser Scala2.10.0 REPL Fehler?

FYI Scala2.9.2 REPL folgt

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

Antwort

2

Dies ist definitiv wie ein REPL Bug aussieht.

Beachten Sie, dass der Konstruktor korrekt gekennzeichnet ist als private (in anderen Worten, new A(1) nicht kompiliert werden, wie erwartet), ist es nur die Fabrik (A.apply), die zu Unrecht öffentlich ist.

-3

Die REPL hat einen großen semantischen Unterschied w.r.t. der gewöhnliche Compiler.

Überlegen Sie, was es bedeutet in der Lage zu sein, dies zu tun:

scala> val v1 = 23 
v1: Int = 23 

scala> val v1 = 42 
v1: Int = 42 

Können Sie, dass in kompilierten Scala-Code? Natürlich nicht, es wäre eine verbotene Doppeldefinition.

Wie macht die REPL das? Im Endeffekt befindet sich jede Zeile, die Sie eingeben, in einem zunehmend verschachtelten Bereich. Die Erscheinung der Neudefinition ist eine tatsächliche Verschattung. Es ist, als ob Sie das getan hätten:

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

Also, wie bekommen Sie Begleiter? Setzen Sie ein explizites Objekt (oder ein anderes bereichsbildendes Konstrukt) um sie herum. Und denken Sie daran, keine Leerzeilen. Die REPL wird die Eingabe für eine bestimmte "Zeile" oder einen "Block" nicht mehr akzeptieren, wenn Sie dies tun.

+0

https://gist.github.com/4770890 –

+0

Was ist Ihr Punkt ? Das kann auch außerhalb der REPL nicht als Scala kompiliert werden. –

+0

@Mef: Wow ... Ich habe es total versäumt, meinen Standpunkt mit 'v2' zu verdeutlichen! Danke, dass du das getan hast. –

-2

Ich sehe ... Sie denken, Sie rufen den Konstruktor, wenn Sie A(1) schreiben. Du bist nicht. Sie rufen die Factory, die für Sie hinzugefügt wurde, im automatisch generierten (öffentlichen) Companion-Objekt und seiner öffentlichen Methode apply auf.

Nachtrag

Mein Tag wiederholt falsch ...

Im 2.10.0 REPL sein:

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) } 
+1

Ich glaube nicht, dass er die Fabrik mit dem Konstruktor mischt, vorausgesetzt, der Titel lautet "scala case class private apply-Methode (repl bug?)". Es ist eigentlich der Scala-Compiler/REPL, der verwirrend ist und über den Konstruktor redet, wenn wir wirklich versuchen, die Fabrik zu nennen. –

+0

@ RégisJean-Gilles: Er tut es. Sie verwenden den Konstruktor nur direkt, wenn Sie das Schlüsselwort 'new' verwenden. –

+1

Ich denke, du verpasst den Punkt. Dies ist eine ** Fallklasse **. Wenn der Konstruktor "privat" gemacht wird, soll die entsprechende Fabrik ebenfalls "privat" gemacht werden. Genau das passiert, wenn Sie sein Code-Snippet kompilieren, aber das Verhalten ist aus irgendeinem Grund anders in der REPL. –