最近、列挙型クラスの1つをサブクラスとしてオブジェクトを含むシールクラスにアップグレードしました。これにより、抽象化の別の層を作成してコードを簡略化できます。ただし、Enum.values()
関数を介してすべての可能なサブクラスを取得することはできなくなりました。これは、その機能に大きく依存しているため、悪いことです。リフレクションまたは他のツールでそのような情報を取得する方法はありますか?
PS:手動でアレイに追加することはできません。現在45件ありますが、さらに追加する予定です。
これは私たちの密封されたクラスがどのように見えるかです:
sealed class State
object StateA: State()
object StateB: State()
object StateC: State()
....// 42 more
値のコレクションがある場合は、次のような形になります。
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>>
、リフレクションを使用して、独自のクラス階層をそこから具体的なオブジェクトに拡張および作成することもできます。例えば:
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では、直接拡張はサポートされなくなりました。Enumクラスを明示的に拡張するためのDisallow:KT-7773を参照してください。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加