2015-06-25 13 views
9

tworzę Kotlin klasy z atrybutem klasy, który chcę, aby zainicjować w konstruktorze:Kotlin: Inicjalizacja atrybut klasy w konstruktorze

public class TestClass { 

    private var context : Context? = null // Nullable attribute 

    public constructor(context : Context) { 
     this.context = context 
    } 

    public fun doSomeVoodoo() { 
     val text : String = context!!.getString(R.string.abc_action_bar_home_description) 
    } 
} 

niestety muszę zadeklarować atrybut jako Nullable z „? " sign, chociaż atrybut zostanie zainicjowany w konstruktorze. Zgłaszanie tego atrybutu jako atrybutu Nullable sprawia, że ​​zawsze konieczne jest wymuszenie wartości NonNull za pomocą "!!" lub do sprawdzenia wartości Null za pomocą "?".

Czy można tego uniknąć, jeśli atrybut klasy zostanie zainicjowany w konstruktorze? Chciałbym doceniają rozwiązania jak ten:

public class TestClass { 

    private var context : Context // Non-Nullable attribute 

    public constructor(context : Context) { 
     this.context = context 
    } 

    public fun doSomeVoodoo() { 
     val text : String = context.getString(R.string.abc_action_bar_home_description) 
    } 
} 
+0

Drugim przykładem jest praca z Kotlin 0.12.213. Jakiej wersji Kotlin używasz? – D3xter

+0

To działa. Użyłem już 0.12.613. Ale myślę, że robiłem coś złego. Przepraszam! – Christopher

+0

Jest więcej przypadków, dodałem odpowiedź dla pełnego zasięgu. –

Odpowiedz

11

Jeśli jedyne co robisz w konstruktorze jest zadanie, następnie można użyć konstruktora Podstawowej z prywatnej posesji.

np:

public class TestClass(private var context: Context) { 

    public fun doSomeVoodoo() { 
    val text = context.getString(R.string.abc_...) 
    } 
} 
+1

oh, fajnie! Nie wiedziałem tego! – Christopher

14

Jak pokazują D3xter masz możliwość skonfigurowania go w konstruktorze. Masz również inne opcje. Tutaj wszyscy są ...

Tworzenie właściwość w konstruktorze (zgodnie @ D3xter) ten jest najczęstszym przypadku prostych właściwości zainicjowane bezpośrednio przez głównego konstruktora:

class TestClass(private val context: Context) { 
    fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

Możesz zadeklarować właściwość val i nie zainicjować jej, zakładając, że wszystkie możliwe konstruktory faktycznie ją zainicjują (jak na twój drugi przykład w zadawanym pytaniu). Jest to normalne, gdy masz więcej niż jeden konstruktor, które mogłyby zainicjować wartości inaczej:

public class TestClass { 
    private val context: Context 

    public constructor(context : Context) { 
     this.context = context 
    } 

    // alternative constructor 
    public constructor(pre: PreContext) { 
     this.context = pre.readContext() 
    } 

    public fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

można przekazać w parametrów konstruktora, które nie są oświadczenia majątkowe, a następnie używać ich w ciągu inicjowania własności. Jest to powszechne, gdy masz bardziej złożone inicjacji lub trzeba użyć właściwości delegowanych:

class TestClass(context: PreContext) { 
    private val context : Context by lazy { context.readContext() } 
    private val other: List<Items> = run { 
     context.items.map { it.tag }.filterNotNull() 
    } 
    private val simpleThing = context.getSimple() 

    fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

Korzystanie lateinit modifier gdy nie można zainicjować wartości w trakcie budowy, ale masz pewność, że będzie to miało miejsce przed pierwszym dostępem do odczytu. Jest to powszechne, gdy wtrysk zależność, IoC kontenera, lub coś tworzy pusty wersję swojej klasie, a następnie inicjuje go natychmiast:

class TestClass() { 
    private lateinit var context : Context // set by something else after construction 

    fun doSomeVoodoo() { 
     val text : String = context.getString() 
    } 
} 

Dla lateinit nieruchomość musi obecnie być var i nie działa z prymitywny typy.

Możesz również zadeklarować właściwość var i nie można jej zainicjować, jeśli używasz delegata zaprojektowanego do tego celu, takiego jak Delegates.notNull().Jest to podobne do lateinit i wspólne kiedy chcesz var że nie ma stanu początkowego, ale jest ustawiona później po wybudowaniu w nieznanym momencie:

public class TestClass() { 
    private var context: Context by Delegates.notNull() 

    public fun doSomeVoodoo() { 
     // if context is not set before this is called, an exception is thrown 
     val text : String = context.getString() 
    } 
} 
Powiązane problemy