F
F
foonfyrick2020-11-21 10:15:25
Kotlin
foonfyrick, 2020-11-21 10:15:25

How does as work? What is the difference from type conversion?

I have never used this operator, but when I decided to try it, some difficulties arose.
I read that this is a type casting operator, that is, if I have 2 variables of different primitive types, then I can make one different, that is, make int from long, etc., but in fact I catch an error, I read on the Internet, did not understand anything, and did not find examples. Can you give a couple of examples of how to use it?
It seemed to me that type casting and conversion are the same, that is:
var x = 'c'
var y = x.toInt()
or
var y = x as Int

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Denis Zagaevsky, 2020-11-21
@foonfyrick

No, you misunderstood. as is about the parent-child relationship, which the Int, Long and Char you mentioned are not related to. That's why you get errors. What does this mean: you have a value that is of type "parent" and you want to cast it to type "child".
For example:

fun f(n: Number): Int{
   return n as Int
}

f(10) // 10
f(10L) // ClassCastException

By the second example, you can understand what to do type casting, if you do not know exactly what type the instance has, it is fraught with runtime errors.
Therefore, there is a form as? that returns null if it fails. And there is also an is operator that checks if an object is an instance of a certain class:
val x = 10
x is Int == true
x is Number == true
x is Any == true
x is Long == false
x as Int // redundent
val y: Long? = x as? Long //== null

In addition, Kotlin has such a wonderful thing as smartcasts (smart type casting). What does it mean. If the compiler sees that you have checked the type of the value and this value cannot change, then it infers the appropriate type itself, and an explicit cast (as) is not needed. This works for conditionals, if, when, elvis-operator, also if you've cast before.
val x: Any = ...
if (x is String) x.substring(0, 10)
if (x is Int) x + 10

x as Long // Long или ClassCastException
x + 10L // до этой точки выполнение дойдёт только в случае успешного каста.

And of course it all works great with user-defined types, divinely with sealed classes:
sealed class B
class D1(val x: Int): B()
class D2(val y: String): B()
object D3: B()

fun f(b: B){
  when (b){
    is D1 -> b.x 
    is D2 -> b.y
    is D3 -> D3
  }
}

This is useful for returning different values, handling errors, and so on.
Thus, the use of as makes sense in a rather limited number of cases. When the compiler can't prove something, but you know it for sure. For example, in the case of a mutable property, or a function that returns the same value.
The toInt you mentioned is not a type conversion, but an ordinary function that returns a new type according to certain rules.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question