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
时候, lateinit
和lateinit
类似,但是在未知的时间点之后,
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() } }