隐式引用嵌套泛型的基础类型

时间:2021-07-25 05:14:44

标签: kotlin generics

尝试为包装另一个泛型类型的类型实现泛型初始值设定项。

具有用于通用枚举类型的反向映射器

class SerializableEnumMapper<V, T>(
    enumValues: Array<T>
) where T : Enum<T>, T: SerializableEnum<V> {

    private val mapEnum: Map<V, T> = 
        mutableMapOf<V, T>().apply {
            enumValues.forEach {
                this[it.rawValue] = it
            }
        }

    fun getEnum(value: V): T? = mapEnum[value]
}

其中 SerializableEnum 是提供原始值的通用接口。

interface SerializableEnum<T> {
    val rawValue: T
}

现在,对于以下枚举:

enum class SomeEnum(
        override val rawValue: Int
): SerializableEnum<Int> {
    THIRTY_SEVEN(37),
    FORTY_TWO(42)
}

我可以简单地通过以下方式创建映射器:

val someEnumMapper = SerializableEnumMapper(SomeEnum.values())  // Works fine

但只是为了为此提供一个更通用的初始化器,我想要这样的东西:

val anotherEnumMapper = enumMapperOf<SomeEnum>() // How to do this one?

我最接近这个的:

val anotherEnumMapper = enumMapperOf<Int, SomeEnum>() // Still need to provide Int here :(

inline fun <V, reified T> enumMapperOf() where T : Enum<T>, T: SerializableEnum<V> =
        SerializableEnumMapper(enumValues<T>())

有没有办法以我们只需要提供 Enum 类型并且可以隐式引用底层 Int 类型的方式编写?

1 个答案:

答案 0 :(得分:2)

enumMapperOf 的返回类型是 SerializableEnumMapper<V, T>。它有两个泛型类型参数。尽管它们是相关的,但您不能将返回类型声明为 SerializableEnumMapper<T.T, T> (我认为这就是您要问的?),因为这不是一回事。 (不过这在其他语言中是一回事。)您确实需要两个类型参数,并将它们与此处的约束联系起来。

但是,如果您对使用另一种语法感到满意,则可以改用它:

val anotherEnumMapper = enumMapperOf(SomeEnum::class)

inline fun <V, reified T> enumMapperOf(clazz: KClass<T>) where T : Enum<T>, T: SerializableEnum<V> =
    SerializableEnumMapper(enumValues<T>())

这允许您避免编写 Int,但引入了一个“无用”参数 - 它仅用于推断两个通用参数。