简体   繁体   English

在 Kotlin 中返回继承泛型 class 的具体 class

[英]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> .但 Kotlin 无法识别MClickMapperRFMFunction<MClick, Event>的子类。

I tried to add a cast as RFMFunction<MClick, Event> in the when , but that didn't work.我尝试在when中将演员表添加as RFMFunction<MClick, Event> ,但这没有用。

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> Kotlin 无法识别 MClickMapper 是 RFMFunction<MClick, Event> 的子类

That is not entirely correct.这并不完全正确。 The error is Type mismatch: inferred type is MClickMapper but RFMFunction<T, Event> was expected .错误是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 .所以实际上,Kotlin 拒绝将MClickMapper视为RFMFunction<T, Event>的子类,因为T是由 function 的调用者提供的。编译器不知道klass == MClick::class.java意味着那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> ).从技术上讲,您可以在此处使用未经检查的强制转换(因为您比编译器了解的更多),但它应该强制转换为RFMFunction<T, Event> (而不是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?另外,作为旁注,您为什么同时使用KClassreified类型参数? If you reify T , you don't need the explicit KClass :如果您具体化T ,则不需要明确的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.然而,这个解决方案不是很好,因为你有点硬编码MClickMapperMClick之间的关系(在when和 inheritance 层次结构中),这意味着如果这两个地方 go 不同步,你可能会遇到看不到的问题在编译时。 It would be better to use the type information to create the mapping dynamically, so you have the mapping harcoded in a single place.最好使用类型信息动态创建映射,这样您就可以在一个地方对映射进行硬编码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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