2012-01-01 20 views
8

Tôi muốn làm điều gì đó như thế này (ví dụ được đơn giản hóa, nhưng có chứa tất cả các mảnh quan trọng):Puzzle - phơi bày một công tiểu thành viên của thành viên riêng với kiểu tùy chỉnh

class Master 
{ 
    type DataType = Int 
    var counter : DataType = 0 
} 

class Slave(private val master : Master) 
{ 
    val counter = master.counter // (*) 
} 

Và đây (*) tôi nhận được lỗi:

private value master escapes its defining scope as part of type Slave.this.master.DataType

val counter = master.counter

tôi hiểu ra lỗi, nhưng tôi không hiểu được lý do - loại là một phần của lớp Master, không phải là đối tượng master, vì vậy điều quan trọng là nếu lớp là tư nhân, không phải là một đối tượng. Vâng, ít nhất là trong lý thuyết.

Nó rất dễ dàng để thực hiện một workaround nhanh:

val counter : Master#DataType = master.counter 

Nhưng tôi tin rằng đây là một phiên bản rõ ràng của mã chính xác giống như trước, nó "chỉ" mất gõ hơn. Đây có phải là tính năng không?

HỎI:

một loại (đây DataType) Có thể phụ thuộc của đối tượng, và không phải là lớp học (ví dụ: loại định nghĩa cho mỗi thể hiện của lớp) trong Scala?

Trả lời

14

Bạn đang sai khi bạn nghĩ

this is an explicit version of the exactly same code as before

Master#DataTypemaster.DataType hai khác nhau loại.

master.DataType là loại của những trường hợp DataType trường hợp có master làm đối tượng bên ngoài. Nói cách khác, chính xác những gì bạn yêu cầu, nhưng rõ ràng sau đó master một phần của loại và loại không thể được hiển thị nếu không có master.

Master#DataType là loại bất kỳ cá thể nào DataType cho bất kỳ đối tượng bên ngoài nào (tương đương Master.DataType bằng Java).

trả lời nhận xét:

Loại thành viên có thể được ghi đè trong một lớp con (trong đó có một lớp con bưu phẩm có chứa chỉ có một đối tượng), nhưng chỉ bằng một loại tương thích. Và trong ví dụ của bạn DataType đã được cụ thể trong Master, do đó, chỉ lớp tương thích với chính nó. Vì vậy, một cái gì đó như

val a = new Master { 
    override type DataType = String 
} 

sẽ không gõ, điều này có nghĩa: bạn sẽ nhận được var counter: String = 0, điều đó là vô nghĩa. Nhưng

val a = new Master { 
    override type DataType = Int 
} 

sẽ hoạt động (nhưng không quá hữu ích).

Vì vậy, nó chỉ có ý nghĩa để ghi đè trừu tượng loại thành viên. Nhưng chúng được kiểm tra theo kiểu giống như các lớp bên trong, do đó, a.DataType thường không được coi là giống như b.DataType - ngay cả khi chúng không thực sự khác nhau!

+0

Cảm ơn bạn, vì vậy nếu tôi hiểu điều này một cách chính xác (tuy nhiên tôi không đọc nó trong "Lập trình trong Scala" tôi tin - hoặc có thể nó bị trượt), bạn có thể xác định loại cho mỗi thể hiện của lớp, không chỉ cho mỗi lớp . – greenoldman

+0

Cảm ơn bạn đã cập nhật, điều này rất có giá trị, tiếc là tôi không thể upvote bài viết của bạn nhiều hơn 1 :-) – greenoldman

+0

Đây là một trong những điều hữu ích trong Scala có thể là một "gotcha" khi đến từ các ngôn ngữ OOP khác. Câu trả lời rất gọn gàng; giá trị upvote của tôi;). – TechNeilogy