首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >kotlin中Enum<T>的函数变量参数

kotlin中Enum<T>的函数变量参数
EN

Stack Overflow用户
提问于 2021-04-09 19:20:23
回答 1查看 77关注 0票数 0

我有以下枚举,其中每个Enum类实现RatingValue接口,每个伴生对象实现RatingValues<T>接口

代码语言:javascript
运行
复制
enum class Clarity(override val value: Int) : RatingValue {
        EXCELENT(5),
        VERY_GOOD(4),
        GOOD(3),
        FAIR(2),
        POOR(1);

        companion object : RatingValues<Clarity>
    }

    enum class Colour(override val value: Int) : RatingValue {
        EXCELENT(10),
        VERY_GOOD(8),
        GOOD(6),
        FAIR(4),
        POOR(2);

        companion object : RatingValues<Colour>
    }

RatingValues接口有ratings()方法,它被定义为一个扩展:

代码语言:javascript
运行
复制
inline fun <reified T> RatingValues<T>.ratings(): List<Int> where T : RatingValue, T : Enum<T> = enumValues<T>().map { it.value }

我想实现一个接受RatingValue枚举的vararg参数的方法,它可以像这样调用

代码语言:javascript
运行
复制
val cumulativeRating = cumulate(Colour, Clarity)

我的第一个想法是编写以下代码,但是失败了,因为RatingValues的泛型类型参数T明显不同

代码语言:javascript
运行
复制
private inline fun  <reified T> cumulate(vararg ratings: RatingValues<T>) : List<Int> where T: RatingValue, T : Enum<T>  {
        return ratings
            .map(RatingValues<T>::ratings)
            .fold(listOf(0, 0, 0, 0, 0)) { x, y -> x.zip(y, Int::plus) }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-10 06:16:29

可以接受具有不同T的可变参数RatingValues<T>的方法是:

代码语言:javascript
运行
复制
private fun cumulate(vararg ratings: RatingValues<*>): List<Int> {
    return ratings
        .map { it.ratings() }
        .reduce { x, y -> x.zip(y, Int::plus) } //same semantics, but more concise and performant
}

问题是,由于类型擦除,有关T的实际类型的信息将丢失,因此它将被具体化为Object,并且您将得到相当隐蔽的运行时错误:java.lang.NoSuchMethodError: java.lang.Object.values()[Ljava/lang/Object; (在我看来,编译器一开始就不应该编译它,但这不是重点)。

我担心,您必须在RatingValues接口中将ratings()方法定义为非泛型,并在每个枚举的伴生对象中实现它,才能使其正常工作:

代码语言:javascript
运行
复制
interface RatingValues<T> where T : RatingValue, T : Enum<T> {
    fun ratings(): List<Int>
}

inline fun <reified T> RatingValues<T>.ratingsForEnums(): List<Int> where T : RatingValue, T : Enum<T> =
    enumValues<T>().map { it.value }

enum class Clarity(override val value: Int) : RatingValue {
    EXCELENT(5),
    VERY_GOOD(4),
    GOOD(3),
    FAIR(2),
    POOR(1);

    companion object : RatingValues<Clarity> {
        override fun ratings() = ratingsForEnums()
    }
}

enum class Colour(override val value: Int) : RatingValue {
    EXCELENT(10),
    VERY_GOOD(8),
    GOOD(6),
    FAIR(4),
    POOR(2);

    companion object : RatingValues<Colour> {
        override fun ratings() = ratingsForEnums()
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67020166

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档