Kotlin-提取基础类类型

时间:2018-12-14 08:48:25

标签: generics reflection kotlin

所以,我一直在Kotlin反思中徘徊,而我似乎无法做到以下几点:

object ThreadState {

    sealed class State {
object DANCE : State() {val validEvents: List<ThreadEvent> = listOf(ThreadEvent.Weave, ThreadEvent.Bob)}
object DUCK : State() {val validEvents: List<ThreadEvent> = listOf(ThreadEvent.Weave, ThreadEvent.Bob)}
object DODGE : State() {val validEvents: List<ThreadEvent> = listOf(ThreadEvent.Weave, ThreadEvent.Bob)}
.... Code
    }

.... Code
}

我想做的是这样的:

val map = ThreadState.State::class.sealedSubclasses.map{ it to it.simpleName}.toMap()

map[ThreadState.State.DODGE]

让它吐出类的简单名称(在本例中为DODGE)。

原因是因为我可以简单地反转地图并从名称中获取值。即ThreadState.fromString("DODGE") // ThreadState.State.DODGE

但是,当我使用:: sealedSubclasses时,它会给出<KClass <out ThreadState.State>>的列表

这不是布宜诺斯艾利斯,因为我一生无法找到从KClasses列表中的任何给定元素中撤回ThreadState.State的方法。我尝试运行it as ThreadState.State,但它告诉我不能将KClass强制转换为ThreadState.State。

任何帮助将不胜感激。

简而言之-列出密封类的列表,这些密封类是包含值的单例对象。需要制作符合<ThreadState, String>的类的映射,其中ThreadState是ThreadState.State的实例,而字符串只是该类的简单名称。

我真的很愿意接受解决方案-当然不必反思,也欢迎泛型。

2 个答案:

答案 0 :(得分:2)

您在这里:

val stateMap = ThreadState.State::class.sealedSubclasses.asSequence()
  .map { it.simpleName to it.objectInstance } // note the objectInstance call
  .toMap()

还要注意objectInstance的文档:

  

对象声明的实例;如果此类不是对象声明,则为null

出于测试目的,我在您的State类中添加了以下功能:

fun printMe() = println("class: ${this::class.simpleName} object: $this")

现在您可以按以下方式访问对象:

stateMap["DODGE"]?.printMe()
// will then print the same as:
ThreadState.State.DODGE.printMe()

我想走那条路值得,但是您知道用例,我不……也许delegated properties之类的东西对您有用吗?

但是:如果要访问validEvents,则需要确保它也是State类本身的一部分,即,您可能需要添加如下内容:

sealed class State {
  open val validEvents : List<ThreadEvent> = emptyList()

  // and then of course the subclasses need to override it:
  object DANCE : State() {override val validEvents: List<ThreadEvent> = listOf(ThreadEvent.Weave, ThreadEvent.Bob)} 

只有这样,您才能拨打类似的电话:

stateMap["DODGE"]?.validEvents

答案 1 :(得分:1)

map[ThreadState.State.DODGE::class]怎么样?还是不适合您?