2015-06-25 120 views
9

我創建了一個科特林級與類屬性,這是我想在構造函數初始化:科特林:初始化類屬性在構造函數中

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) 
    } 
} 

不幸的是我已經與「申報屬性爲可爲空? 「簽名,但該屬性將在構造函數中初始化。將該屬性聲明爲Nullable屬性使得始終需要強制使用「!!」的NonNull值或用「?」提供空值檢查。

有什麼辦法避免這種情況,如果類屬性將在構造函數初始化?我想明白這樣一個解決方案:

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

第二個例子正在與科特林0.12.213。你使用什麼Kotlin版本? – D3xter

+0

它的工作原理。我已經使用0.12.613。但我認爲,我做錯了什麼。抱歉! – Christopher

+0

有更多的案例可用,我添加了一個完整覆蓋的答案。 –

回答

11

如果您在構造函數中所做的唯一事情是賦值, 那麼你可以使用主構造帶私人財產。

e.g:

public class TestClass(private var context: Context) { 

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

哦,很酷!我不知道! – Christopher

14

如通過D3xter你必須在構造函數中設置它的選項。你也有其他選擇。在這裏,他們都是......

創建構造中的屬性(如每@ D3xter),這是由主構造直接初始化簡單的屬性最常見的情況:

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

您可以聲明val屬性並且不初始化它,假設所有可能的構造函數實際上都初始化它(按照被問題中的第二個示例)。 這是正常的,當你有一個以上的構造函數,可以以不同的初始化值:

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() 
    } 
} 

可以在構造函數的參數不屬於財產申報通過,然後使用這些屬性初始化中。 這是常見的,當你有更復雜的初始化或需要使用委託性質

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() 
    } 
} 

使用lateinit modifier當你無法初始化施工過程中的價值,但你肯定會第一個讀訪問之前完成。 這是常見的,當一個依賴注入,IoC容器,或者說創建類的一個空的版本,然後立即初始化:

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

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

lateinit屬性當前必須是var,不與原工作類型。

如果您使用專門爲此目的設計的代理(如Delegates.notNull()),還可以聲明var屬性並不初始化它。這類似於lateinit,共同當你想要一個var不具有初始狀態,但在未知的時間點後施工後置:

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() 
    } 
}