2013-02-12 15 views
7

in Scala2.10.0 REPLscala classe caso privata metodo apply (repl 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) 

Ma se compilare

$ 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) è errore di compilazione.

questo errore di Scala2.10.0 REPL?

FYI Scala2.9.2 REPL sta seguendo

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

risposta

2

Questo appare sicuramente come un insetto REPL.

Nota che il costruttore sia correttamente contrassegnato come private (in altre parole, new A(1) non si compila, come previsto), è solo la fabbrica (A.apply), che è a torto pubblico.

-3

Il REPL ha un'enorme differenza semantica con. il compilatore ordinario.

considerare che cosa vuol dire essere in grado di fare questo:

scala> val v1 = 23 
v1: Int = 23 

scala> val v1 = 42 
v1: Int = 42 

Puoi fare che nel codice Scala compilato? Certo che no, sarebbe una doppia definizione proibita.

Come funziona il REPL? In effetti ogni linea che inserisci è in un ambito progressivamente più nidificato. L'aspetto della ridefinizione è lo shadowing reale. È come se lo facessi:

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

Quindi, come si ottiene compagni? Metti un oggetto esplicito (o un altro costrutto di formazione di scope) attorno a loro. E ricorda, niente righe vuote. Il REPL smetterà di accettare input per una determinata "linea" o "blocco" quando lo fai.

+0

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

+0

Qual è il tuo punto di ? Questo non riesce a compilare come Scala anche al di fuori del REPL. –

+0

@Mef: Wow ... Non sono riuscito a esprimere il mio punto usando 'v2'! Grazie per averlo risolto. –

-2

Vedo ... Pensi di chiamare il costruttore quando scrivi A(1). Tu non sei. Stai chiamando la factory aggiunta per te nell'oggetto companion (pubblico) generato automaticamente e nel suo metodo pubblico apply.

Addendum

La mia giornata per essere ripetutamente sbagliato ...

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

Non penso che misuri la fabbrica con il costruttore, dato che il titolo è "scala case class metodo privato (repl bug?)". In realtà è lo scalabile compilatore/REPL che confonde e parla di costruttore quando in realtà stiamo cercando di chiamare la fabbrica. –

+0

@ RégisJean-Gilles: Lo fa. Si utilizza direttamente il costruttore solo quando si utilizza la parola chiave 'new'. –

+1

Penso che ti manchi il punto. Questa è una ** case class **. Rendere "privato" il costruttore dovrebbe anche rendere la "fabbrica" ​​corrispondente. Il che è esattamente ciò che accade quando si compila il suo frammento di codice, ma il comportamento è per qualche ragione diverso nel REPL. –