我有以下枚举,其中每个Enum类实现RatingValue接口,每个伴生对象实现RatingValues<T>接口
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()方法,它被定义为一个扩展:
inline fun <reified T> RatingValues<T>.ratings(): List<Int> where T : RatingValue, T : Enum<T> = enumValues<T>().map { it.value }我想实现一个接受RatingValue枚举的vararg参数的方法,它可以像这样调用
val cumulativeRating = cumulate(Colour, Clarity)我的第一个想法是编写以下代码,但是失败了,因为RatingValues的泛型类型参数T明显不同
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) }
}发布于 2021-04-10 06:16:29
可以接受具有不同T的可变参数RatingValues<T>的方法是:
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()方法定义为非泛型,并在每个枚举的伴生对象中实现它,才能使其正常工作:
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()
}
}https://stackoverflow.com/questions/67020166
复制相似问题