This question is a derivative of a recent one I made here
While that one was resolved, I immediately faced a new one of a similar nature, but I am also not able to find a solution for it.
Sample example:
abstract class Endpoint<T>() {
private val myList: MutableList<(T) -> Unit> = mutableListOf()
fun <E : T> addToList(cbk: (E) -> Unit) { <-- E extends T
myList.add(cbk)
}
}
Usage example would be
Some sealed class
sealed class MainSealedClass {
data class ChildClass(val someParam: Int): MainSealedClass()
}
And the function call
anEndpointInstance.addToList<ChildClass>{it: ChildClass ->
// do something here
}
I tried doing the following, but it looks like it is not is not allowed
val myList: MutableList<(out T) -> Unit> <--- Unsupported error shows up
Is there a way to do this without having to add an extra declaration at the class level?
I considered using inline reified
but the function needs to access private fields of the Endpoint
instance, so I do not want to use that option.
CodePudding user response:
I don't think the language supports specifying variance of the parameters of a functional type, or references to functions with generic types that aren't defined. For example, if you want to get a reference to a generic function, you have to specify its generic types in the functional type declaration.
There is dubious usefulness here anyway. If you had a list of functions that each have different input types, then when you retrieve a function from the list, you won't be able to call it because you won't know which input type it supports. You might as well have a MutableList<Any>
.
CodePudding user response:
Thanks to Tenfour04's knowledge, I was able to find a workaround to my issue. I do not consider this to be a fix for my issue, but given that it apparently cannot be done as I expected, the next best thing was to work around the issue with the help of a wrapper.
Here is how my code turned out with the work using the sample in my question
abstract class Endpoint<T>() {
private val myList: MutableList<(T) -> Unit> = mutableListOf()
fun add(cbk: (T) -> Unit) {
myList.add(cbk)
}
inline fun <reified N : T> addToList(crossinline callback: (N) -> Unit) {
add { if (it is N) callback.invoke(it) }
}
}
And its usage is the way I wanted in my question, nothing changes at this point.