Reputation: 22637
In Java, I'd write something like this:
if (foo != null && foo.bar()) { ...
However Kotlin complains that:
Smart cast to 'Foo' is impossible, because 'foo' is a mutable property that could have been changed by this time
I think it's saying what I wrote isn't thread-safe. However, in the context where I'm using it I know it is as this will always be invoked on a single thread.
Yes foo
needs to be mutable. I realize that making foo
a val
would solve this but that is not possible here.
What's the correct idiom in Kotlin to handle this case?
Upvotes: 2
Views: 1451
Reputation: 170713
In case where the condition is not just a function call, e.g.
foo != null && foo.bar() > 0
you can use let
or run
:
if (foo.let { it != null && it.bar() > 0 }) { ... }
if (foo.run { this != null && bar() > 0 }) { ... }
Upvotes: 1
Reputation: 93531
In this case, a null-safe call returns a Boolean? so you can check if it equals true
:
if (foo?.bar() == true) {
}
If you need non-null foo
inside the conditional, then you can use the common ?.let
idiom.
foo?.let { foo ->
if (foo.bar()) {
}
}
If you know it’s only accessed on this same thread, the !!
operator would be safe after the null check, but ?.let
is more idiomatic so easier to follow once you’re used to reading Kotlin.
Upvotes: 3
Reputation: 70257
The trick is to use Kotlin's excellent null-safety operators to avoid having to do redundant checks.
First, we use the safe-call operator.
foo?.bar()
This is a Boolean?
(i.e. a nullable Boolean) which is null if foo
is null, or the result of bar()
if not. Now, a Boolean?
is not a valid condition in an if statement, obviously, so we need to provide a "default" value of false
. We do that using the amusingly-named Elvis operator
if (foo?.bar() ?: false) { ... }
If foo
is null, then foo?.bar()
is null, and ?:
returns the value of the right-hand side, i.e. false
. If foo
is non-null, then foo?.bar()
is the result of calling bar()
on foo
, and (assuming that result is also non-null), ?:
returns the existing non-null Boolean value.
Upvotes: 2