Reputation: 31
I wish to find solution to force emit(S.() -> S)
function to accept as parameters, only methods from generic S
class. Current solution accepts all lambda methods which returns S.
S is a generic class which has methods to reduce/modify own parameters. I want only those methods to be called in emit
. It guarantees that every method passed to emit is "pure function" (all methods in S are pure)
val _uiState = MutableLiveData<S>()
var state: S
fun emit(reduction: S.() -> S) {
state = reduction.invoke(state)
if (_uiState.value != state) {
_uiState.postValue(state)
}
}
Upvotes: 1
Views: 148
Reputation: 170723
For this, functions simply aren't an appropriate type. I'd declare a type whose values correspond to methods of S
, so
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)
}
}
With some effort, Transform
can be auto-generated (e.g. using an annotation processor, as you mention in a comment), but it may not be worth it depending on how many classes and methods you need to handle and how often they change.
Upvotes: 2