Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast super class object to sub class object in Kotlin?

Here I am trying to converting superclass object to subclass. I am getting the runtime error as "class can not be cast".

Eg :

class Animal {}
class Cat : Animal() {}

class abc {
fun abcd(): Animal {
    return Animal()
}

fun getData() {
    val cat: Cat = abcd() as Cat     //Giving me runtime error.
}
}
like image 225
Appcapster Avatar asked Jan 19 '26 00:01

Appcapster


2 Answers

You can't cast a base class 'instance' to a descendant class, because a base class does not necessarily implement the behaviors of its descendants neither knows anything about them.

In your specific example the method abcd() returns an instance of the base class Animal, and therefore such can't be cast to Cat, since Animal may not have any of the behaviors defined in Cat.

An example, imagine you had also a Dog class, and both Cat and Dog implement different methods such as dog.fetch() and cat.jump(). Such behaviors don't exist in the base class Animal, and therefore it can't be explicitly cast to a specific animal.

The opposite is valid, so casting Cat to Animal, because Cat inherits the behaviors of its base class Animal.

Instead, what you can do is to instantiate a Cat in abcd(), and still return Animal:

fun abcd(): Animal {
    return Cat()
}

This is valid, and the casting will work. But, you must pay attention to avoid potential ClassCastException's at runtime if mixing up derived classes, for example if instantiating a Dog while the return type is Animal and try to use it as Cat.

Small remark: I'm assuming the reason Animal isn't open in your example is just a copy/paste mistake, as it clearly needs such keyword to allow inheritance.

like image 147
PerracoLabs Avatar answered Jan 21 '26 14:01

PerracoLabs


Maybe what you are trying to do is something like creating a type and based on what sub-type then do something, like this:

sealed class Animal

data class Cat(val...) : Animal()
data class Dog(val...) : Animal()

class YourMapper {
    fun animal(condition: Type): Animal {
        return when(condition) {
            ... -> Dog(...)
            ... -> Cat(...)
        }
    }

    fun getData(condition: Type): Animal {
        return animal(condition)
    }

And then the usage is

val data = YourMapper().getData(condition)
when(data) {
  is Dog -> {/*do something with your dog*/}
  is Cat -> {/*do something with your cat*/} 
}

like image 28
cutiko Avatar answered Jan 21 '26 14:01

cutiko