你需要生成RatingValues接口来访问Enum<T>和RatingValue的方法。
但是由于接口甚至它们的虚拟成员都不允许具体化泛型,因此您必须将这些方法转换为扩展:
interface RatingValues<T>
inline fun <reified T> RatingValues<T>.ratings(): List<Int> where T : RatingValue, T : Enum<T> = enumValues<T>().map { it.value }
inline fun <reified T> RatingValues<T>.cumulativeRating(): Int where T : RatingValue, T : Enum<T> = ratings().sum()
用法:
enum class MarkFoo(override val value: Int) : RatingValue {
EXCELENT(5),
VERY_GOOD(4),
GOOD(3),
FAIR(2),
POOR(1);
companion object : RatingValues<MarkFoo>
}
问题是这些方法不能也被声明为抽象接口成员,因为在这种情况下扩展会被遮蔽。因此,它们现在只能针对特定的Ts(枚举,实现RatingValue 接口)在此接口上调用,并且不能被覆盖。对于其他类型的接口将是空的,没有任何方法可以覆盖:
class X(override val value: Int) : RatingValue
class XX : RatingValues<X> {
override fun ratings(): List<Int> { /*...*/ } //Impossible now
override fun cumulativeRating(): Int { /*...*/ } //Impossible now
}
val res = XX.ratings() // Will not compile now since X is not enum
如果您也打算以上述方式使用此接口,那么您必须像以前一样声明接口,只添加一个扩展名但名称不同(如ratingsForEnums),并在每次实现此接口时添加一些样板对于枚举:
interface RatingValues<T> {
fun ratings(): List<Int>
fun cumulativeRating(): Int = ratings().sum()
}
inline fun <reified T> RatingValues<T>.ratingsForEnums(): List<Int> where T : RatingValue, T : Enum<T> = enumValues<T>().map { it.value }
enum class MarkFoo(override val value: Int) : RatingValue {
EXCELENT(5),
VERY_GOOD(4),
GOOD(3),
FAIR(2),
POOR(1);
companion object : RatingValues<MarkFoo> {
override fun ratings() = ratingsForEnums()
}
}
如果您打算仅使用枚举来使用此接口,那么在接口级别上显式地对T 施加限制是有意义的:
interface RatingValues<T> where T : RatingValue, T : Enum<T>