Cast Anonymous (Any) object to class object in kotlin

Viewed 9764

Kotlin compiler is giving me error while running below :

fun main() {
    val x = object {
        val i = 1
        val k = "s"
    }
    val y = x as Planet
    if (y is Planet) {
        println("Hello " + x.i)
    }
}


data class Planet(
        var i : Int,
        var k : String
)

Error :

Exception in thread "main" java.lang.ClassCastException: FileKt$main$x$1 cannot be cast to Planet at FileKt.main (File.kt:7)
at FileKt.main (File.kt:-1) at sun.reflect.NativeMethodAccessorImpl.invoke0 (NativeMethodAccessorImpl.java:-2)

I am unable to understand why i am not able to cast Any object type to specific class object. Isn't all Kotlin classes inherit from Any super class?

please let me know what i am doing wrong here.

2 Answers

Kotlin is a strongly statically typed language. Every variable and every expression has a type that is known at compile time.

In your example you are not specifying the type, but that does not mean it is unknown at compile time. Kotlin uses type inference to determine its type. In your case Any.

val x: Any = object {
    // ...
}

Any is the root of the Kotlin class hierarchy. Every Kotlin class has Any as a superclass. This is the reason why you can not cast Any to Planet at runtime.

What you could do is using Kotlin safe-cast as? which returns null instead of an exception:

val planet: Planet? = x as? Planet

What you also can do, if you ever casted a Planet to Any, you can cast it back to Planet.

data class Planet(val name: String)
    
val pluto: Planet = Planet("Pluto")
val anyPlanet: Any = pluto
val planet: Planet = anyPlanet as Pluto

Thanks to Selvins comments for pointing me to right direction, the problem with my implementation is that i am trying to convert an object to type that is not Planet.

But the problem is that i needed to implement some way to screen the incoming object that is supposed to be of type Planet.

So below is the new implementation where i am checking for property of Planet against the anonymous object, if i get object with any fields other than what is present in Planet it will do nothing.

fun main() {
    val x = object {
        val i = 1
        val k = "s"
    }
    val i = Planet::class.java.declaredFields.asIterable()
    val j = x.javaClass.declaredFields.asIterable()

    val b = i.zip(j).all { (f, a) -> f.name == a.name }
    if (b){
        x.let {
            val p = Planet(i=it.i,k=it.k)
            Log.d("TAG","$p")
        }
    }    
}

data class Planet( val i: Int, val k: String)

May be not the best way, but feel free to comment.

Related