2013-02-12 29 views
7

trong Scala2.10.0 REPLscala trường hợp lớp tin áp dụng phương pháp (repl lỗi?)

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) 

Nhưng nếu biên dịch

$ 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) là biên dịch lỗi.

là lỗi REPL Scala2.10.0 này?

FYI Scala2.9.2 REPL đang theo

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

Trả lời

2

này chắc chắn trông giống như một lỗi REPL.

Lưu ý rằng hàm tạo được đánh dấu đúng là private (nói cách khác, new A(1) không biên dịch, như mong đợi), nó chỉ là nhà máy (A.apply) bị công khai sai.

-3

REPL có một sự khác biệt lớn về mặt ngữ nghĩa w.r.t. trình biên dịch thông thường.

Hãy xem xét những gì nó có nghĩa là để có thể làm điều này:

scala> val v1 = 23 
v1: Int = 23 

scala> val v1 = 42 
v1: Int = 42 

bạn có thể làm điều đó trong mã Scala biên soạn? Tất nhiên là không, nó sẽ là một định nghĩa kép bị cấm.

REPL làm như thế nào? Thực tế, mọi dòng bạn nhập vào đều nằm trong phạm vi lồng nhau dần dần. Sự xuất hiện của redefinition là shadowing thực tế. Nó giống như bạn đã làm điều này:

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

Vì vậy, làm thế nào để bạn có được bạn đồng hành? Đặt một đối tượng rõ ràng (hoặc cấu trúc hình thành phạm vi khác) xung quanh chúng. Và hãy nhớ, không có dòng trống. REPL sẽ ngừng chấp nhận đầu vào cho "dòng" hoặc "chặn" nhất định khi bạn thực hiện.

+0

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

+0

điểm của bạn là gì ? Điều đó không thể biên dịch như Scala bên ngoài REPL, quá. –

+0

@Mef: Wow ... Tôi hoàn toàn thất bại trong việc sử dụng 'v2'! Cảm ơn bạn đã sửa lỗi đó. –

-2

Tôi hiểu ... Bạn nghĩ rằng bạn đang gọi cho nhà xây dựng khi bạn viết A(1). Bạn không phải. Bạn đang gọi nhà máy được thêm vào cho bạn trong đối tượng đồng hành được tạo tự động (công khai) và phương thức công khai apply.

Phụ Lục

ngày tôi phải lặp đi lặp lại sai ...

Trong 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

Tôi không nghĩ rằng anh ta trộn nhà máy với nhà xây dựng, cho rằng tiêu đề là "scala case class private apply method (repl bug?)". Nó thực sự là trình biên dịch scala/REPL gây nhầm lẫn và nói về constructor khi thực sự chúng tôi đang cố gắng gọi cho nhà máy. –

+0

@ RégisJean-Gilles: Anh ấy có. Bạn chỉ sử dụng hàm tạo trực tiếp khi bạn sử dụng từ khóa 'new'. –

+1

Tôi nghĩ bạn đang thiếu điểm. Đây là trường hợp ** **. Việc tạo ra hàm tạo 'private' được cho là làm cho nhà máy tương ứng là' private'. Đó là chính xác những gì sẽ xảy ra khi bạn biên dịch đoạn mã của mình, nhưng hành vi là vì một số lý do khác nhau trong REPL. –

Các vấn đề liên quan