Home > Enterprise >  Kotlin invoke function from sealedSubclasses
Kotlin invoke function from sealedSubclasses

Time:12-17

I would like to check the behavior of overridden function in objects that extend a class without explicitly list them all.

sealed class Food{
    open fun optTemp(): Int{
        return 0
    }
}

object Soup : Food() {
    override fun optTemp(): Int {
        return 65
    }
}

object Cake : Food() {
    override fun optTemp(): Int {
        return 20
    }
}

object Rice : Food() {
    override fun optTemp(): Int {
        return 80
    }
}

object Meat : Food() {
    override fun optTemp(): Int {
        return 60
    }
}

I would like get all the object with overridden function and invoke them like this:

val subclasses: List<KClass<*>> = Food::class.sealedSubclasses

    for (item in subclasses){
//        item.optTemp()

    }

How do I do that?

CodePudding user response:

Assuming all the sealed subclasses are objects, you can get the object instance using objectInstance, and cast it to Food. This cast is safe because of the assumption.

for (subclass in Food::class.sealedSubclasses) {
    val result = (subclass.objectInstance as Food).optTemp()
    println("$subclass - $result")
}

Note that the output is not in any particular order:

class Cake - 20
class Meat - 60
class Rice - 80
class Soup - 65

As Tenfour suggested in the comments, an enum class might be more suitable in this case.

enum class FoodEnum {
    SOUP { override fun optTemp() = 65 },
    CAKE { override fun optTemp() = 20 },
    RICE { override fun optTemp() = 80 },
    MEAT { override fun optTemp() = 60 };
    open fun optTemp() = 0
}

You can then do:

for (value in FoodEnum.values()) {
    println("${value.name} - ${value.optTemp()}")
}

Not only does this not involve reflection, the output will also be in the order in which you have declared the enum constants:

SOUP - 65
CAKE - 20
RICE - 80
MEAT - 60

If the sealed subclasses are not all objects, then you need to somehow find instances of each sealed subclass, cast to Food if needed, and call optTemp on them. After all, optTemp is an instance method, so you need an instance to call it.

  • Related