- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
最近我们将其中一个枚举类升级为密封类将对象作为子类,这样我们就可以创建另一层抽象来简化代码。但是,我们不能再通过 Enum.values()
函数获得所有可能的子类,这很糟糕,因为我们严重依赖该功能。有没有办法通过反射或任何其他工具来检索这些信息?
PS:手动将它们添加到数组中是 Not Acceptable 。目前有 45 个,并且计划增加更多。
这就是我们的密封类的样子:
sealed class State
object StateA: State()
object StateB: State()
object StateC: State()
....// 42 more
如果有一个 values 集合,它将是这个形状:
val VALUES = setOf(StateA, StateB, StateC, StateC, StateD, StateE,
StateF, StateG, StateH, StateI, StateJ, StateK, StateL, ......
自然没有人愿意养这样一个怪物。
最佳答案
在 Kotlin 1.3+ 中,您可以使用 sealedSubclasses
.
在以前的版本中,如果您将子类嵌套在基类中,那么您可以使用 nestedClasses
:
Base::class.nestedClasses
如果您在基类中嵌套其他类,则需要添加过滤。例如:
Base::class.nestedClasses.filter { it.isFinal && it.isSubclassOf(Base::class) }
请注意,这会为您提供子类,而不是这些子类的实例(与 Enum.values()
不同)。
对于您的特定示例,如果 State
中的所有嵌套类是你的object
状态然后您可以使用以下内容获取所有实例(如 Enum.values()
):
State::class.nestedClasses.map { it.objectInstance as State }
如果你想变得更漂亮,你甚至可以扩展 Enum<E: Enum<E>>
并使用 reflection 从它创建您自己的类层次结构到您的具体对象.例如:
sealed class State(name: String, ordinal: Int) : Enum<State>(name, ordinal) {
companion object {
@JvmStatic private val map = State::class.nestedClasses
.filter { klass -> klass.isSubclassOf(State::class) }
.map { klass -> klass.objectInstance }
.filterIsInstance<State>()
.associateBy { value -> value.name }
@JvmStatic fun valueOf(value: String) = requireNotNull(map[value]) {
"No enum constant ${State::class.java.name}.$value"
}
@JvmStatic fun values() = map.values.toTypedArray()
}
abstract class VanillaState(name: String, ordinal: Int) : State(name, ordinal)
abstract class ChocolateState(name: String, ordinal: Int) : State(name, ordinal)
object StateA : VanillaState("StateA", 0)
object StateB : VanillaState("StateB", 1)
object StateC : ChocolateState("StateC", 2)
}
这样您就可以像调用任何其他 Enum
一样调用以下命令:
State.valueOf("StateB")
State.values()
enumValueOf<State>("StateC")
enumValues<State>()
更新
扩展 Enum
Kotlin 不再支持直接。看 Disallow to explicitly extend Enum class : KT-7773 .
关于kotlin - 如何获取给定密封类的所有子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44784328/
当数据类扩展包含非抽象 open val 属性的密封类时,生成的子数据类包含与父类的私有(private)字段重复的私有(private)字段。 sealed class Foo(open val f
当封装一个.jar 文件(整个.jar,而不是特定的包)时,实际上封装了哪些包?它只是包含.class 文件的包,还是还包含父包和子包? 举个例子,假设我有一个包含单个 .class 文件 com.c
我可以很容易地为这样的密封案例类族一般派生一个编解码器: import io.circe._ import io.circe.generic.auto._ sealed trait Base case
我有一个类层次结构: class C1 { virtual object M1(); } class C2: C1 { override sealed object M1(); } class C3:
有什么区别: type MovieType = {| +blob?: string, +name: string, +url?: string |}; 和 type MovieType =
想象一个这样的 secret : apiVersion: v1 kind: Secret metadata: name: {{ include "test-cicd.fullname" . }}
因此,我的一位开发人员使用这样的函数为 Magento 电子商务网站制作自定义导航: getUrl() ?>">__('about') ?> 唯一的问题是它的输出如下: about 据我了解,如果同时
我是一名优秀的程序员,十分优秀!