Safe-call演算子
Kotlin書く人でSafe-call演算子?.
を使わない人は少ないんじゃないかと思います。
それだけ当たり前に使う演算子なのですが、先日軽くはまったところがあるので、紹介します。
class A {
fun foo():Unit = Unit
fun bar():Int = 0
}
こんなクラスがあったとします。
それをこんな風に使います。
val a : A? = null
a?.foo()
a?.bar()
まあ、思った通りに動きます。a==null
なので、foo()もbar()も実行されません。
では、これならどうでしょう?
val a : A? = null
a?.foo() ?:hoge()
a?.bar() ?:huga()
hoge(),huga()が両方とも実行されて欲しい、というケースです。
これ、なぜかIDE上ではa?.foo()
のところに警告が出ます。Elvis Operator (?:) always returns the left operand of non-nullable type Kotlin.Unit
どうやら、foo()はUnitを返すので、a?.foo()
もUnitになりnull
にはならない、よってエルビスの右辺は実行されないよ、と警告されているようです。
警告を信じている限り、hoge()は実行されないように思われます。
bar()の方はIntを返すので、a?.bar()
がInt?と解釈されるので問題ない、ということのようです。
では、実行してみましょう。
=========: HOGE
=========: HUGA
あれ?
hoge()が実行されてますね。
どうも、コンパイラとエラーチェッカーの間に齟齬があるようです。
まとめ
nullable?.let { doit() } ?: instead()
こんな風に?.let { }
を交えた構文を
if ( nullable != null ){
doit()
}else{
instead()
}
の代わりとして、手癖で覚えてたらIDEに警告されて悩んだ、という話でした。
個人的には、警告の解釈の方が筋が通ってるように思えるんですが、
動いてる方が正しいとも言えるわけで……難しい。
いまのところ、警告を無視するしか無さそうです。