2016-01-27 11 views
5

以下のコードがあります。それはコトリンです。どんな考えでtextToSpeechからtextToSpeech.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) 
        } 
       } 

      }) 

私はそれがバグをプラグインアイデアkotlinですが、実際に

答えて

7

Kotlinは、変数の初期化政策を硬化した、そして今変数を参照することは禁止だがコンパイルできないようだと仮定lambdaとオブジェクト式でも初期化子の内部では妥当と思われます。ラムダが変数代入の直前に呼び出されたとします。あなたのケースでは

、私はこれはかなり面倒な構築物にobject expressionを使用して回避策として提案することができます:それはvalueプロパティを通じて受け入れられるの内側

val textToSpeech = object { 
    val value: TextToSpeech get() = inner 
    private val inner = TextToSpeech(
      applicationContext, 
      { value.setLanguage(Locale.UK) } 
    ) 
}.value 

これはinnerで匿名オブジェクトを初期化します。 innerイニシャライザはvalueプロパティを使用します。その後、valueを抽出して使用することができます。

しかし、このトリックが危険であることに注意してください:実行時に、valueを使用してinnerが割り当てられる前に(例えばTextToSpeechコンストラクタで)NullPointerExceptionをスローします。

また、私はSAM conversionを使ってラムダをOnInitListenerに置き換えましたが、それでもオブジェクト式を使用することができます。


UPD:チェック this questionこのアプローチを一般化するために努力しています。それを使用して、あなたは書くことができます

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

sources on Githubを参照してください。