Kotlin:在构造函数中初始化类属性

我创建了一个类属性的Kotlin类,我想在构造函数中进行初始化:

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

如果你在构造函数中做的唯一的事情是一个赋值,那么你可以使用一个私有属性的主构造函数。

例如:

 public class TestClass(private var context: Context) { public fun doSomeVoodoo() { val text = context.getString(R.string.abc_...) } } 

如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修饰符 ,但是您确定在第一次读取访问权限之前完成该操作。 当依赖注入,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()Delegates.notNull() ,则还可以声明var属性并不初始化它。 当你想要一个没有初始状态的lateinit时候, lateinitlateinit类似,但是在未知的时间点之后,

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