13

này không hoạt động như mong đợi (kể từ khi tôi đang cố gắng để gọi một gói tin run từ bên ngoài Services):Scala: Truy cập gói phương pháp có thể nhìn thấy thông qua các loại cấu trúc bên ngoài gói

object Services { 
class HelloPrinter { 
    private[Services] def run = "Hello" 
    } 
} 

val obj = new Services.HelloPrinter 

Nhưng, đáng ngạc nhiên làm việc này:

val obj: {def run: String} = new Services.HelloPrinter 
obj.run 

Tôi sẽ nói, lỗi của trình biên dịch vì HelloPrinter không khớp với loại cấu trúc vì quy tắc hiển thị gói, không nên biên dịch!

Đây là một trường hợp chương trình biên dịch nhưng nó ném một ngoại lệ thời gian chạy (java.lang.NoSuchMethodException):

class HelloPrinter { 
    private[HelloPrinter] def run = "Hello" 
} 

val obj: {def run: String} = new HelloPrinter 
obj.run 

Đây có phải là một tính năng ngôn ngữ hoặc loại trừ tôi đang thiếu hoặc hợp pháp một lỗi trong Scala?

+2

Rất thú vị. Bạn đã thử chạy với REPL 'scala -feature'? Nó cho thấy rõ ràng rằng có một cuộc gọi phản xạ được gọi. Tôi đoán phạm vi và bất biến là tất cả ra khỏi cửa sổ khi nói đến sự phản ánh. – marios

+2

Cũng như xa như tôi có thể nói cảnh báo là nhiều hơn dự định để làm cho bạn thận trọng về những hậu quả có thể thực hiện. Sự hiểu biết của tôi là mặc dù sử dụng sự phản chiếu để thực hiện cuộc gọi thực tại thời gian chạy, việc gõ cấu trúc (được cho là) ​​được đánh máy tĩnh như bất kỳ thứ gì khác trong scala, vì trình biên dịch sẽ kiểm tra xem chữ ký có khớp đúng không. thành công). Trừ khi tất nhiên bạn thực hiện một downcast rõ ràng cho một loại cấu trúc. Tuy nhiên ở đây không có diễn viên, trình biên dịch đơn giản dường như bỏ qua việc kiểm tra khả năng hiển thị của phương thức. –

+0

Ví dụ thứ hai mà bạn nói ném một 'NoSuchMethodException' không biên dịch cho tôi (trong 2.10.4 và 2.11.6 REPL). –

Trả lời

4

Trên mức hiển thị cấp JVM được điều chỉnh cho các kiểu/loại xung quanh không tồn tại. Trình biên dịch Scala sẽ tạo ra một phương thức công khai trong trường hợp này và xử lý khả năng hiển thị này trong nội bộ.

Nếu bạn sử dụng các kiểu cấu trúc, trình biên dịch sẽ phản ánh truy cập một cách phản ánh các thành viên thuộc loại này. Nó sẽ không kiểm tra các cờ hiển thị đặc trưng của Scala nhưng chỉ có các cờ được xác định trong mã bytecode Java.

Bạn không đề cập đến phiên bản trình biên dịch Scala nào bạn đang sử dụng nhưng tôi cho rằng đây là lỗi trong phiên bản cụ thể của bạn. Tôi nhận được kết quả tương tự như Jasper-M khi cố gắng biên dịch nó. Lý do là phương thức được trình biên dịch tạo ra thực sự được đặt trước bằng tên kiểu, tức là HelloPrinter$$run trong trường hợp này. Mã sau sẽ thực hiện:

val x: { def HelloPrinter$$run: String } = new HelloPrinter 
x.run 

Một lần nữa trình biên dịch Scala chỉ tạo phương pháp công khai và quản lý khả năng hiển thị nội bộ. Nó không phải là một tính năng mà là một lỗi mà trình biên dịch không kiểm tra khả năng hiển thị Scala-internal cho các kiểu cấu trúc.

+1

Đã có sự cố mở chưa? Nếu không, tôi có thể nộp không? – pathikrit

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