Лямбда как параметр функции -> принимать методы только из определенного класса - PullRequest
1 голос
/ 27 мая 2019

Я хочу найти решение, чтобы заставить emit(S.() -> S) функцию принимать в качестве параметров, только методы из общего S класса.Текущее решение принимает все лямбда-методы, которые возвращают S. S - универсальный класс, который имеет методы для уменьшения / изменения собственных параметров.Я хочу, чтобы в emit вызывались только эти методы.Это гарантирует, что каждый метод, переданный в emit, является «чистой функцией» (все методы в S чистые)

val _uiState = MutableLiveData<S>() 
var state: S
fun emit(reduction: S.() -> S) {
        state = reduction.invoke(state)
        if (_uiState.value != state) {
            _uiState.postValue(state)
        }
    }

1 Ответ

2 голосов
/ 27 мая 2019

Для этого функции просто не подходят.Я бы объявил тип, значения которого соответствуют методам S, поэтому

class S { 
    fun method1(x: String): S = ...
    fun method2(): S = ...
    ...

    sealed class Transform {
        operator fun invoke(s: S): S = when(this) {
            is Method1 -> s.method1(x)
            is Method2 -> s.method2()
            ...
        }

        class Method1(val x: String) : Transform
        object Method2 : Transform
    }
}

fun emit(reduction: S.Transform) {
    state = reduction.invoke(state)
    if (_uiState.value != state) {
        _uiState.postValue(state)
    }
}

С некоторым усилием Transform может быть сгенерировано автоматически (например, с использованием процессора аннотаций, как вы упомянули вкомментарий), но это может не стоить того, в зависимости от того, сколько классов и методов вам нужно обработать и как часто они меняются.

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