Как сохранить функцию (или лямбду) внутри карты, а затем выполнить ее? - PullRequest
0 голосов
/ 04 января 2019

Я хотел бы иметь MutableMap, который отображает классы по некоторой логике.Он в основном используется для реагирования на некоторые объекты, поступающие из бэкэнда.Например,

class ViewUpdater(val view: RecordingActivity) {
    val map: MutableMap<KClassifier, Function<*>> = mutableMapOf()

    init {
        map[Entity1::class] = { m: Entity ->
            view.entity1.text = (m as Entity1).value1.toString()
        }
        map[Entity2::class] = { m: Entity ->
            view.entity2.text = (m as Entity2).value2.toString()
        }
}

Но я не знаю, является ли тип Function<*> правильным.После этого, очевидно, я хотел бы выполнять свои функции / лямбды, когда в руке есть конкретный объект: например,

 .subscribe(
            { it: Entity ->
                   map[it::class] // and what next here... ?
                }
            }

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Вы ищете оператора invoke().В вашем случае вы можете просто сделать:

.subscribe { map[it::class]?.invoke(it) }

Обратите внимание, что это может вернуть null, если у вас не была сопоставлена ​​функция для определенного подкласса Entity.В качестве альтернативы, я мог бы предложить использовать оператор when в качестве функции расширения для удобочитаемости, если вы намереваетесь отобразить определенные подклассы Entity в String.Например:

fun Entity.toSpecialString() : String = when(this) {
    is Entity1 -> value1.toString()
    is Entity2 -> value2.toString()
    else -> "unspecified"
}

Тогда вы можете просто сделать:

.subscribe { it.toSpecialString() }
0 голосов
/ 04 января 2019

вы можете использовать:

MutableMap < KClass<Entity>, (Entity) -> Unit >  = mutableMapOf()

или:

MutableMap < KClass<Entity>, Function1<Entity, Unit> >  = mutableMapOf()

вместо использования карты вы можете использовать этот метод :

fun <T: Entity> setViewText(en: T) =
             when(en){
               is Entity1 -> view.entity1.text = en.value1.toString()
               is Entity2 -> view.entity2.text = en.value2.toString()
               else -> throw Exception("Invalid Entity")
             }

вы не получаете подпись подписи, но я думаю вы можете запустить ее следующим образом (если подписка получает лямбда-аргумент как (Entity) -> Unit и имеет получателя сущности):

.subscribe{ map[this::class] } // if subscribe has Entity receiver

еслиподписка не имеет получателя сущности:

.subscribe{ map[it::class]?.invoke(it) }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...