経緯
俺「Javaを使っていたけど、これからはKotlinだ! まずは TextView での文字列の表示のあたりから。」
俺「textView.setText("文字列")
っと。ほとんどJavaと変わらないけど、セミコロンが不要になったのはいいな」
Android Studio「セッターメソッドの呼び出しをプロパティ構文に置き換えられるよ!」
俺「なるほど!プロパティ構文で書けるのか、textView.text = "文字列"
っと。いいね!」
俺「さて、じゃあ TextView の派生クラスである EditText の方も書き換えよう。 editText.text = "文字列"
っと」
Kotlin「Type mismatch: inferred type is String but Editable! was expected
」
俺「え?」
Kotlin「Editable
じゃないとダメです。String
なら setText()
を使って。」
俺「...」
理由
TextView#getText()
の戻り値の型は CharSequence
1 だが、
EditText#getText()
の戻り値の型は Editable
2 となっているため。
どういうことか
なぜセッター(setText()
)ではなく、ゲッター(getText()
)の話が出てきたかというと
Javaで定義されたゲッター/セッターをKotlinからプロパティ構文でアクセスする際、型の推論にはゲッターの戻り値の型が使用されるため。
(ちなみに、セッターしか無く対応するゲッターが無い場合にはプロパティ構文すら使えない)
メソッドのオーバーライド時に、戻り値の型を派生型(Editable
は CharSequence
の派生型)に変えることは許されているので、こんな事態となってしまっている模様。
(´・ω・`)
それでもプロパティ構文が使いたい
TextView に明示的にキャストする
(editText as TextView).text = "文字列"
基底クラスにキャストするという一見「?」なコードにはなってしまう。
(別) Editable
に変換する
editText.text = Editable.Factory.getInstance().newEditable("文字列")
インスタンス生成を伴うのでパフォーマンスが重視される場面では注意。