In multiple cases you might've came across the situation where you have to cast a global variable and check the instance beforehand.
A most common case in Android environment is to check whether the (hosting) activity implements a callback or extended from Specific one.
Before
if (activity is BaseActivity) {
(activity as BaseActivity).hideKeyboard()
}
After
Same can be written in sweet Kotlin syntax in a single line
(activity as? BaseActivity)?.hideKeyboard()
From the official doc
Use the safe cast operator as? that returns null on failure.
How this is better?
In surface it might not look like a better code overhaul. As calls to activity increase in numbers, it gets better.
// CreateTweetFragment.kt
fun submit() {
// Fire and forget API call
if (activity is BaseActivity) {
(activity as BaseActivity).hideKeyboard()
}
if (activity is TweetSubmittedCallback) {
(activity as TweetSubmittedCallback).onTweetSubmitted()
}
}
We could easily cast the activity to the exact subclass and invoke both methods.
// CreateTweetFragment.kt
fun submit() {
// Fire and forget API call
if (activity is TwitterActivity) {
(activity as TwitterActivity).hideKeyboard()
(activity as TwitterActivity).onTweetSubmitted()
}
}
But it enforces the CreateTweetFragment to be attached to the TwitterActivity to execute both statements. Anything that is just a BaseActivity or TweetSubmittedCallback won't execute the statement even though the implementation is in place.
Prefer composition over inheritance
Now with the as?
operator, both statements can be executed independent of each other.
fun submit() {
// Fire and forget API call
(activity as? BaseActivity)?.hideKeyboard()
(activity as TweetSubmittedCallback)?.onTweetSubmitted()
}
Top comments (1)
Nice! I usually do something like this for getting the extras from the bundle in the onCreate. You can also do something like:
val myFoo = myBar as? Boo ?: RuntimeException("myBar should be Boo")
// myFoo is Boo here. Usually I do things like this when I know for sure that I should have a variable of type Boo. You can do things like this with Context or Bundle values.