我有以下代码。这是Kotlin。知道为什么来自textToSpeech
的{{1}}告诉textToSpeech.setLanguage(Locale.UK)
没有解析参考?
textToSpeech
起初我认为它是一个Idea kotlin插件错误,但似乎它实际上无法编译
答案 0 :(得分:8)
Kotlin已经强化了变量初始化策略,现在禁止在其初始化程序中引用变量,即使在lambdas和对象表达式中也是如此,这似乎是合理的:想象一下在变量赋值之前立即调用lambda。
对于您的情况,我可以建议在这个非常繁琐的构造中使用object expression作为解决方法:
val textToSpeech = object {
val value: TextToSpeech get() = inner
private val inner = TextToSpeech(
applicationContext,
{ value.setLanguage(Locale.UK) }
)
}.value
这将初始化一个内部为inner
的匿名对象,该对象可通过value
属性接受。请注意,inner
初始值设定项使用value
属性。然后提取value
并可以使用。
但请记住,这个技巧是不安全的:在运行时,在分配value
之前使用inner
(例如在TextToSpeech
构造函数中)将抛出NullPointerException
。< / p>
此外,我已使用SAM conversion将OnInitListener
替换为lambda,但是仍然可以在那里使用对象表达式。
val textToSpeech = selfReference {
TextToSpeech(
applicationContext,
{ self.setLanguage(Locale.UK) }
)
}
答案 1 :(得分:0)
这是解决该问题的一种非常容易理解的清晰方法。首先,您应该定义以下内容:
fun <T> selfReferenced(initializer: () -> T) = initializer.invoke()
operator fun<T> T.getValue(any: Any?, property: KProperty<*>) = this
稍后使用
val valueName: ValueType by selfReferenced{
//here you can create and use the valueName object
}
以您的问题为例,您可以执行以下操作:
val textToSpeech:TextToSpeech by selfReferenced {
TextToSpeech(
applicationContext,
TextToSpeech.OnInitListener { status ->
if (status == TextToSpeech.SUCCESS) {
textToSpeech.setLanguage(Locale.UK)
}
})
}
在selfReferenced块内,您可以不受限制地使用外部对象。您唯一需要注意的是明确声明类型,以避免递归类型检查问题。