Issue
when i call some api, i wished use multiple callback with generic parameter.
so i defined CallBackData class
class CallBackData<T>(val func: (T?) -> Boolean, val params: T?)
it not data class. because it super class of other callbacks.
and i define Array<CallBackData<*>> variable for multiple callback.
val callbackDts : Array<CallBackData<*>> = arrayOf(
CallBackData(::sampleCallback1, SomeClass(1)),
CallBackData(::sampleCallback2, "hello"),
CallBackData(::sampleCallback3, -1),
)
but when i call func, it say error
Type mismatch.
Required: Nothing?
Found: Any?
i don't get it. why? isn't same it.params type T is same of it.func(param(T))? right? why is Nothing Type? why is not same?
this is full code
fun start(){
val callbackDts : Array<CallBackData<*>> = arrayOf(
CallBackData(::sampleCallback1, SomeClass(1)),
CallBackData(::sampleCallback2, "hello"),
CallBackData(::sampleCallback3, -1),
)
callApi(callbackDts)
}
fun callApi(callbacks : Array<CallBackData<*>>){
callbacks.forEach{
it.func(it.params)
}
}
fun sampleCallback1(params: SomeClass?) : Boolean {
println("sampleCallback1 ${params.toString()}")
return true
}
fun sampleCallback2(params: String?) : Boolean {
println("sampleCallback2 $params")
return true
}
fun sampleCallback3(params: Int?) : Boolean {
println("sampleCallback3 $params")
return true
}
data class SomeClass(val i:Int)
class CallBackData<T>(val func : (T?) -> Boolean, val params: T?)
i tried convert to like this (using out keyword), but it's failed same.(Lambda's parameter type is Nothing?)
fun start(){
val callbackDts : Array<CallBackData<out Any?>> = arrayOf(
CallBackData(::sampleCallback1, SomeClass(1)),
CallBackData(::sampleCallback2, "hello"),
CallBackData(::sampleCallback3, -1),
)
callApi(callbackDts)
}
fun callApi(callbacks : Array<CallBackData<out Any?>>){
callbacks.forEach{
it.func(it.params)
}
}
fun sampleCallback1(params: SomeClass?) : Boolean {
println("sampleCallback1 ${params.toString()}")
return true
}
fun sampleCallback2(params: String?) : Boolean {
println("sampleCallback2 $params")
return true
}
fun sampleCallback3(params: Int?) : Boolean {
println("sampleCallback3 $params")
return true
}
data class SomeClass(val i:Int)
class CallBackData<T>(val func : (T?) -> Boolean, val params: T?)
i look forward to your reply. thanks!
Solution
Unfortunately, the type information of T is gone once you projected a CallbackData<T> to CallbackData<*>. It is no longer known that it.func takes the same type as it.params.
But you do know that they are the same type in the CallBackData class itself, don't you? So you can just add a call method
class CallBackData<T>(val func : (T?) -> Boolean, var params: T?) {
fun call() = func(params)
}
and
callbacks.forEach{
it.call()
}
Or you can overload the invoke operator:
operator fun invoke() = func(params)
You would then be able to do it() directly.
Even if you don't have control over CallBackData, you can still add an extension function:
operator fun <T> CallBackData<T>.invoke() = func(params)
Answered By - Sweeper
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.