2017-08-20 49 views
5

mam następujące klasy Kotlin na Androida:Kotlin - Jak zrobić pole tylko do odczytu dla klas zewnętrznych

class ThisApplication: Application() { 

    lateinit var network: INetwork 

    override fun onCreate() { 

     super.onCreate() 

     network = Network() 
    } 
} 

Teraz każda klasa zewnętrzna może uzyskać INetwork odwołanie po prostu robi:

application.network 

jednak, że także umożliwia klasa zewnętrzny, aby zastąpić tę wartość:

application.network = myNewNetworkReference 

I chcesz uniknąć drugiej opcji. Niestety, nie mogę utworzyć pola val, ponieważ jego inicjalizacja musi nastąpić wewnątrz wywołania zwrotnego onCreate.

Myślałem także o zrobieniu pole prywatne i narażając go przez funkcję, jak ten:

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

Jednak kto nazywa getNetwork() nadal można przypisać nową wartość do niego tak:

application.getNetwork() = myNewNetworkReference 

Jak ustawić, aby pole sieciowe było tylko do odczytu według klas zewnętrznych? A może jeszcze lepiej, czy jest jakiś sposób, aby to uczynić val, mimo że nie mogę go zainicjować wewnątrz konstruktora?

+0

To nieprawda, że ​​osoba wywołująca metodę może ponownie przypisać wartość tej metody. 'application.getNetwork() = myNewNetworkReference' nie skompilowałoby się. – yole

Odpowiedz

3

Aby ograniczyć dostęp z klas zewnętrznych, można zmienić widoczność dostępowych. W Twoim przypadku, musisz private setter i public getter z lateinit modyfikatora:

lateinit var network: INetwork 
    private set 

Lub tylko do odczytu właściwości leniwe:

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

istnieją pewne nieporozumienie z panem o tym kodzie:

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

Kotlin to pass-by-value co jako Java does. Tak więc application.getNetwork() = myNewNetworkReference nie jest prawidłową instrukcją. Nie możemy przypisać wartości do zwracanej wartości funkcji.

2

Czy dla Twojego scenariusza zadziałałaby val network: INetwork by lazy { ... }?

Wyrażenie lambda zostaje wywołane z pierwszym odniesieniem do pola network. Oczywiście nie jest to to samo, co odroczenie inicjowania do metody OnCreate, ale jest to sposób na uczynienie go val bez konieczności inicjowania go w konstruktorze.

Dostępne są również inne opcje delegacji. The Kotlin documentation jest warte sprawdzenia.

+0

To będzie działać w tym konkretnym przypadku, ponieważ klasa Network nie przyjmuje żadnych parametrów. Dziękuję Ci. Uprościłem nieco ten przykład.Potrzebuję sposobu, aby polegać na onCreate, ponieważ niektóre tworzone przeze mnie instancje wymagają zainicjowania obiektu Context. Na przykład, mogę utworzyć instancję SQLDatabase (this) i musi ona znajdować się wewnątrz onCreate, ponieważ przekazuję do niej "this" (Context). – Tiago

2

Można zmodyfikować widoczność pobierające/ustawiające independantly ze zmiennej rzeczywistej:

lateinit var network: INetwork 
    private set