< Back to | Open article on dev.to

Kotlin safe casting

Kotlin safe cast operator

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()
}
Enter fullscreen mode Exit fullscreen mode

After

Same can be written in sweet Kotlin syntax in a single line

(activity as? BaseActivity)?.hideKeyboard()
Enter fullscreen mode Exit fullscreen mode

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()
  }
}
Enter fullscreen mode Exit fullscreen mode

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()
  }
}
Enter fullscreen mode Exit fullscreen mode

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()
}
Enter fullscreen mode Exit fullscreen mode
In multiple cases you might've came across the situation where you have to cast a global variable a...