gpt4 book ai didi

generics - Kotlin 外投影类型禁止使用

转载 作者:IT老高 更新时间:2023-10-28 13:45:17 26 4
gpt4 key购买 nike

我最近在 Kotlin 中尝试了以下内容。这个想法是我将接收一个扩展 BaseItemItem(例如 AmericanItem)作为输入。我正在尝试为每个这些项目使用不同的解析器这是一个示例代码

abstract class BaseItem
class AmericanItem : BaseItem()
class EuropeanItem : BaseItem()

interface ItemParser<T : BaseItem> {
fun parse(item: T)
}

class AmericanItemParser : ItemParser<AmericanItem> {
override fun parse(item: AmericanItem) {
println("AmericanItemParser")
}
}

class EuropeanItemParser : ItemParser<EuropeanItem> {
override fun parse(item: EuropeanItem) {
println("parsing EuropeanItem")
}
}

fun main(args: Array<String>) {
val hashMap = HashMap<Class<out BaseItem>, ItemParser<*>>()
hashMap.put(AmericanItem::class.java, EuropeanItemParser())
hashMap.put(EuropeanItem::class.java, AmericanItemParser())

val inputItem = EuropeanItem()
val foundParser = hashMap[inputItem.javaClass]
foundParser?.parse(inputItem)
}

我的问题在最后一行,当我尝试调用解析器时,我收到以下编译错误

Out-projected type 'ItemParser<*>?' prohibits the use of 'public abstract fun parse(item: T): kotlin.Unit defined in ItemParser'

我在这里做错了什么?

最佳答案

您在 Map 的声明之间产生了冲突。和ItemParser . map 可以包含 BaseItem 的任何后代但是 ItemParser设计为每个后代只对 BaseItem一个 后代进行操作.所以对于 ItemParser 的给定实例它必须接受它可以识别的东西,在这里你不能这样做,因为你的foundParser可以是任何后代,而不是给定 ItemParser 的真正预期类型实例。其中T它应该猜吗?!?它不能。

因此,您必须围绕基类而不是后代来设计 API。您使编译器无法知道传递给 parse() 的内容。方法。你能知道的唯一一件真实的事情是它是一个 BaseItem实例。

只有 知道您使用 map 所做的技巧,以确保您使用正确的类型调用正确的实例。编译器不知道您的逻辑可以保证这一点。

我建议您更改 API 以添加 internalParse使用通用 parse 包裹的方法双重检查并执行邪恶转换的函数。

abstract class BaseItem

class AmericanItem : BaseItem()
class EuropeanItem : BaseItem()

interface ItemParser<T: BaseItem> {
@Suppress("UNCHECKED_CAST")
fun parse(item: BaseItem) {
val tempItem = item as? T
?: throw IllegalArgumentException("Invalid type ${item.javaClass.name} passed to this parser")
internalParse(tempItem)
}

fun internalParse(item: T)
}

class AmericanItemParser : ItemParser<AmericanItem> {
override fun internalParse(item: AmericanItem) {
println("AmericanItemParser")
}
}

class EuropeanItemParser : ItemParser<EuropeanItem> {
override fun internalParse(item: EuropeanItem) {
println("parsing EuropeanItem")
}
}

fun main(args: Array<String>) {
val hashMap = HashMap<Class<out BaseItem>, ItemParser<*>>()
hashMap.put(AmericanItem::class.java, EuropeanItemParser())
hashMap.put(EuropeanItem::class.java, AmericanItemParser())

val inputItem = EuropeanItem()
val foundParser = hashMap[inputItem.javaClass]
foundParser?.parse(inputItem)
}

请注意,您也可以使用 Kotlin 类代替 KClass<out T> 类型的 Java 类。 .

关于generics - Kotlin 外投影类型禁止使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53093601/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com