kotlin - 与迭代 Kotlin 中枚举值的泛型方法的接口
问题描述
假设这些接口
interface RatingValue {
val value: Int
}
interface RatingValues {
fun ratings() : List<Int>
fun cumulativeRating() : Int = ratings().sum()
}
还有一堆类似于这个的枚举
enum class MarkFoo(override val value: Int) : RatingValue {
EXCELENT(5),
VERY_GOOD(4),
GOOD(3),
FAIR(2),
POOR(1);
companion object : RatingValues {
override fun ratings() = values().map(MarkFoo::value)
}
}
有没有办法将 rating() 函数的实现一般提取到 RatingValues 接口中,以避免在所有枚举的同伴中具有基本相同的完全相同的实现?每个枚举都将实现 RatingValue,并且每个枚举都有一个实现 RatingValues 的同伴
解决方案
您需要生成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>
}
问题是这些方法不能也被声明为抽象接口成员,因为在这种情况下扩展会被遮蔽。所以他们现在只能在这个接口上调用特定T
的s(枚举,实现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>
推荐阅读
- arrays - netlogo:数组问题:来自列表(过滤器
- python-3.x - How would I change this tuple back into string to be written in a file?
- gradle - 错误:Gradle 5.0 中删除了对使用低于 3.0 的工具 API 版本的客户端的支持
- windows - Windows Server 2016 1607 上的 Windows 容器中的 Jenkins
- r - How to convert the output from readLines into a dataframe
- rest - 如何在 Drupal 8 中对自定义插件(资源)自动应用更改更改
- mobile - P2P messaging over internet
- php - 动态产品列表页面php
- php - Laravel 5.7.28 覆盖 getAuthPassword 仍然会引发未定义的索引:密码
- c# - 异步运行 C# WPF 事件