androidkotlingenerics

Kotlin: Get list item of certain type passed in function


Trying to get list item of certain type passed in function. This code works as expected, but it looks not so good. Can I check classes types into firstOrNull lambda directly, instead of comparing names?

fun <T: TripManagerModule> getModule(moduleType: KClass<T>): T? {
    return modules
        .firstOrNull { it::class.simpleName == moduleType.simpleName }
        ?.let { it as? T } //Warning here: "Unchecked cast: TripManagerModule to T"
}

val module = getModule(TripArrivalDelayManager::class)

Solution

  • You can utilize filterIsInstance() that preserves the type of the list:

    fun <T : TripManagerModule> getModule(moduleType: KClass<T>): T? =
        modules
            .filterIsInstance(moduleType.java)
            .firstOrNull()
    

    You don't need to cast anymore, it will already be of the correct type.

    And if you want to get rid of the parameter you can make the function inline:

    inline fun <reified T : TripManagerModule> getModule(): T? =
        modules
            .filterIsInstance<T>()
            .firstOrNull()
    

    You can then call it like this

    val module = getModule<TripArrivalDelayManager>()
    

    or let the compiler infer the type, for example like this:

    val module: TripArrivalDelayManager? = getModule()