読者です 読者をやめる 読者になる 読者になる

そーす

福岡在住のプログラマ

KotlinからJavaのクラスを利用するときにAccessorが上手く生成されないことがある

f:id:saburesan:20160906091652j:plain

Kotlin小ネタなんですが、KotlinからJavaのクラスを利用するときにjavaのSetter, GetterメソッドからKotlinのAccecorに自動で変換してくれる機能があります。

例えば、 Java側で

class Text {
...
public void setText(String text) {...}

public String getText() {...}
}

このようなTextクラスをKotlin側で利用する場合

val text = Text()
text.text = "hoge" //setter
text.text              //getter "hoge"が返る

このように使うことが出来ます。

基本的には非常に便利なのですが、Java側のSetter/Getterの定義の仕方で上手く動作しない場合があるようです。

AndroidのEditTextクラスで起きました。

EditTextクラスにはEditable getText(), _setText(Charsequence c)というメソッドがあります。

Setter/Getterで型が違うのですがKotlin側ではtextアクセサが生成されます。

補完にもsetText, getTextは無いです。

f:id:saburesan:20170212233107p:plain

そして型はEditableになっています。

型がEditableになっているのでtextアクセサ経由でStringクラスをセット出来なくなります!!!

AndroidStudio上だとこのようにエラーになります。

f:id:saburesan:20170212231444p:plain

画像見てもらうと分かるように、setText(“”)と書いている部分は警告も何も出ていません。

Kotlinのアクセサが使える場合にJavaのSetter/Getterを書くと画像のgetText()のように黄色い波線で警告が出ます。

f:id:saburesan:20170212231859p:plain

しかし、setText(“”)の方は何も出ていません。

ということはKotlinが生成したtextアクセサのSetterはsetText()と別物と解釈されているということです。

でもtextアクセサとsetTextの定義を見てみるとどちらも同じTextView#setText(Charsequence text)を参照しています。

試しにKotlinバイトコードデコンパイルしてJavaのコードを見てみると…

Kotlin

f:id:saburesan:20170212232717p:plain

Java

f:id:saburesan:20170212232749p:plain

やはり同じでしたね。

わざわざEditableのサブクラスに変換したのにCharsequenceにキャストすんのかい。

とは言え、setText(Editable)という存在しないメソッドがKotlin側で定義されちゃってるようですね。

これはバグなんですかね。