简体   繁体   中英

Returning concrete class that inherits generic class in Kotlin

I'm trying to do the following:

 inline fun <reified T> getMapper(klass: Class<T>): RFMFunction<T, Event> =
    when (klass) {
      MClick::class.java -> MClickMapper
      else -> { throw RuntimeException("Unknown event type: $klass") }
    }

with:

object MClickMapper : RFMFunction<MClick, Event>()

but Kotlin doesn't recognize that MClickMapper is a subclass of RFMFunction<MClick, Event> .

I tried to add a cast as RFMFunction<MClick, Event> in the when , but that didn't work.

The error I get is:

Type mismatch.
Required: RFMFunction<T, Event>
Found: ClickMapper

Is there a way to do that?

Thanks!

Kotlin doesn't recognize that MClickMapper is a subclass of RFMFunction<MClick, Event>

That is not entirely correct. The error is Type mismatch: inferred type is MClickMapper but RFMFunction<T, Event> was expected .

So in fact, Kotlin refuses to consider MClickMapper as a subclass of RFMFunction<T, Event> , because T is provided by the caller of your function. The compiler doesn't go as far as knowing that klass == MClick::class.java means that T == MClick . You could technically use an unchecked cast here (since you know more than the compiler), but it should be a cast to RFMFunction<T, Event> (not RFMFunction<MClick, Event> ). And then you can suppress the unchecked cast warning.

Also, as a side note, why do you use both a KClass and a reified type argument? If you reify T , you don't need the explicit KClass :

@Suppress("UNCHECKED_CAST")
inline fun <reified T> getMapper(): RFMFunction<T, Event> = when (T::class) {
    MClick::class -> MClickMapper as RFMFunction<T, Event>
    else -> throw RuntimeException("Unknown event type: ${T::class}")
}

However, this solution is not great , because you kinda hardcode twice the relationship between MClickMapper and MClick (in the when AND in the inheritance hierarchy), which means if those 2 places go out of sync you can have problems that won't be seen at compile time. It would be better to use the type information to create the mapping dynamically, so you have the mapping harcoded in a single place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM