2016-01-27 95 views
5

我有下面的代碼。這是Kotlin。任何想法爲什麼textToSpeechtextToSpeech.setLanguage(Locale.UK)是說textToSpeech沒有參考解決?匿名Kotlin聽衆內部未解決的參考

val textToSpeech = TextToSpeech(
      applicationContext, 
      object : TextToSpeech.OnInitListener { 
       override fun onInit(status: Int) { 
        if (status == TextToSpeech.SUCCESS) { 
         textToSpeech.setLanguage(Locale.UK) 
        } 
       } 

      }) 

起初,我以爲這是科特林插件錯誤的想法,但似乎它實際上無法編譯

回答

7

科特林硬化變量初始化政策,它現在禁止引用變量在它的初始化器內部,即使在lambda表達式和對象表達式中,這似乎也是合理的:想象一下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

另外,我用SAM conversion代替了OnInitListener,它的lambda表達式很短,但仍然可以在那裏使用對象表達式。


UPD:檢查 this question我努力推廣這種方法。使用它,你可以寫

val textToSpeech = selfReference { 
    TextToSpeech(
     applicationContext, 
     { self.setLanguage(Locale.UK) } 
    ) 
} 

查看sources on Github