Kotlin - Извлечь базовый тип класса - PullRequest
0 голосов
/ 14 декабря 2018

Итак, я бился в отражении 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>>

Это не Буэно, потому что я не могу на всю жизнь найти способполучить ThreadState.State обратно из любого данного элемента в списке KClasses.Я попытался запустить it as ThreadState.State, но он сказал мне, что KClass не может быть приведен к ThreadState.State.

Любая помощь будет высоко ценится.

Короче - есть список запечатанныхклассы, которые являются одноэлементными объектами, содержащими значения.Необходимо составить карту классов, которая соответствует <ThreadState, String>, где ThreadState является экземпляром ThreadState.State, а строка - просто простым именем класса.

Я действительно открыт для решений - конечноне должно быть отражения, дженерики тоже приветствуются.

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Вот, пожалуйста:

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()

Я сомневаюсь, что стоит пойти по этому пути, но вы знаете вариант использования, я не ... может быть, что-то вроде делегированные свойства может быть полезным для вас?

Однако: если вы хотите получить доступ к 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
0 голосов
/ 14 декабря 2018

как насчет map[ThreadState.State.DODGE::class]?Или это не применимо для вас?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...