2015-06-25 170 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() 
    } 
}