2017-08-20 30 views
5

Tôi có lớp sau Kotlin trên Android:Kotlin - Làm thế nào để làm cho lĩnh vực read-only cho các lớp bên ngoài

class ThisApplication: Application() { 

    lateinit var network: INetwork 

    override fun onCreate() { 

     super.onCreate() 

     network = Network() 
    } 
} 

Bây giờ, bất kỳ lớp bên ngoài có thể nhận được INetwork tài liệu tham khảo bằng cách đơn giản thực hiện:

application.network 

Tuy nhiên, đó cũng làm cho nó có thể cho một lớp bên ngoài để ghi đè lên giá trị đó:

application.network = myNewNetworkReference 

tôi muốn tránh tùy chọn thứ hai. Thật không may, tôi không thể tạo trường val vì khởi tạo của nó cần xảy ra bên trong cuộc gọi lại onCreate.

Tôi cũng nghĩ về việc làm lĩnh vực tư nhân và phơi bày nó thông qua một chức năng, như thế này:

private lateinit var network: INetwork 
fun getNetwork() = network 

Tuy nhiên, bất cứ ai gọi getNetwork() vẫn có thể gán một giá trị mới cho nó, như vậy:

application.getNetwork() = myNewNetworkReference 

Tôi làm cách nào để trường chỉ có thể đọc được trường mạng? Hoặc thậm chí tốt hơn, có cách nào để làm cho nó val mặc dù tôi không thể khởi tạo nó bên trong một nhà xây dựng?

+0

Không đúng khi người gọi phương thức có thể gán lại giá trị của phương pháp này. 'application.getNetwork() = myNewNetworkReference' sẽ không biên dịch. – yole

Trả lời

3

Để hạn chế việc truy cập từ các lớp bên ngoài, bạn có thể thay đổi hiển thị accessors. Đối với trường hợp của bạn, bạn cần private setter và public getter với lateinit modifier:

lateinit var network: INetwork 
    private set 

Hoặc một thuộc tính chỉ đọc lười biếng:

val network: INetwork by lazy { Network() } //you can access private property here, eg. applicationContext 

Có một số hiểu lầm từ bạn về mã này:

private lateinit var network: INetwork 
fun getNetwork() = network 

Kotlin là pass-by-value như những gì Java does. Vì vậy, application.getNetwork() = myNewNetworkReference không phải là một tuyên bố hợp lệ. Chúng tôi không thể gán giá trị cho giá trị trả về của hàm.

2

Liệu val network: INetwork by lazy { ... } có hoạt động cho kịch bản của bạn không?

Biểu thức lambda được gọi với tham chiếu đầu tiên đến trường network. Rõ ràng, điều này không giống như trì hoãn khởi tạo phương thức OnCreate, nhưng nó là một cách để làm cho nó val mà không cần phải khởi tạo nó trong hàm tạo.

Cũng có các lựa chọn ủy quyền khác. The Kotlin documentation đáng để trả tiền.

+0

Điều này sẽ làm việc cho trường hợp cụ thể này vì lớp Mạng không có bất kỳ tham số nào. Cảm ơn bạn. Tuy nhiên, tôi đã đơn giản hóa ví dụ một chút.Tôi cần một cách để dựa vào onCreate vì một số trường hợp tôi sẽ tạo ra cần một đối tượng Context đã được khởi tạo. Ví dụ, tôi có thể khởi tạo một SQLDatabase (điều này) và nó cần phải được bên trong onCreate bởi vì tôi đang chuyển "this" (Context) cho nó. – Tiago

2

Bạn có thể thay đổi khả năng hiển thị của getters/setters independantly từ biến thực tế:

lateinit var network: INetwork 
    private set 
Các vấn đề liên quan