2016-01-27 22 views
5

Mam poniższy kod. To jest Kotlin. Każdy pomysł, dlaczego textToSpeech z textToSpeech.setLanguage(Locale.UK) mówi, że nie ma odniesienia rozwiązane dla textToSpeech?Niewyjaśnione odniesienie wewnątrz anonimowego słuchacza Kotlina

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

      }) 

Początkowo zakłada się, że jest to pomysł Kotlin plugin błąd, ale wydaje się, że w rzeczywistości nie mogą być skompilowane

Odpowiedz

7

Kotlin stwardnieje polityki zmiennych inicjalizacji, i to teraz zakazane odwoływać się do zmiennej w jego inicjatorze, nawet w lambdach i wyrażeniach obiektowych, co wydaje się rozsądne: wyobraź sobie, że lambda jest wywoływana bezpośrednio przed przypisaniem zmiennej.

Twoim przypadku, mogę zaproponować jako obejście stosując object expression w tym dość skomplikowana konstruktem:

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

ta zainicjuje anonimowy obiekt z inner wewnątrz, które jest do przyjęcia przez value nieruchomości. Należy zauważyć, że inicjator inner używa właściwości value. Następnie value jest wyodrębniany i może być używany.

Ale proszę pamiętać, że ta sztuczka jest niebezpieczne: w czasie pracy, przy użyciu value przed inner jest przypisany (na przykład w TextToSpeech konstruktora) rzuci NullPointerException.

Ponadto zastąpiłem OnInitListener za pomocą lambda, używając SAM conversion, aby było krótkie, ale można nadal tam użyć wyrażenia obiektowego.


UPD: sprawdź this question za mój wysiłek uogólnienia tego podejścia. Używając go, możesz napisać:

Zobacz .