【问题标题】:kotlin Generic type function as parameterskotlin 泛型函数作为参数
【发布时间】:2020-06-06 16:05:02
【问题描述】:

我遇到了一些关于 kotlin 中 generic 类型的问题。最初,我想用值和调用函数调用函数。所以我在下面写了这个,但是这个值只允许我传递一个像 string/Int 这样的类型。我想在调用函数中传递一个函数作为参数。

A类

ClassA<T>{
var canCancel: Boolean = true
var recallFunction: (() -> T)? = null
var recallFunctionWithValue: ((value: T) -> Unit)? = null
var context: Context? = null
var value: T? = null
var functionPara :( ()->T)? = null
var recallFunctionWithFunction:((()->T) -> Unit)? = null

constructor(context: Context?, canCancel: Boolean, value: T, recallFunctionWithValue: (value: T) -> Unit) {
this.context = context
this.canCancel = canCancel
this.value = value
this.recallFunctionWithValue = recallFunctionWithValue
}
}

B类

ClassA(ctx, true,viewModel!!::testRefInside,viewModel!!::testRefOutside).createNativeNetworkDialog()

视图模型

fun testRefOutside(test: Observable<Any>? ){

}
fun testRefInside():Observable<Any>?{
    return null
}

我尝试做类似的事情

var canCancel: Boolean = true
var recallFunction: (() -> T)? = null
var recallFunctionWithValue: ((value: T) -> Unit)? = null
var context: Context? = null
var value: T? = null
var functionPara :( ()->T)? = null
var recallFunctionWithFunction:((()->T) -> Unit)? = null

    constructor(context: Context?, canCancel: Boolean, value: () -> T, recallFunctionWithValue: (value: ()->T) -> Unit) {
    this.context = context
    this.canCancel = canCancel
    this.functionPara = value
    this.recallFunctionWithFunction = recallFunctionWithValue
}

但它显示语法错误。有人可以帮忙吗?

语法错误

Error

Error2

Error show in this place only RYEasyDialog means ClassA


有效!!现在

  var recallFunctionWithFunction:((value: T) -> Unit)? = null
    constructor(context: Context?, canCancel: Boolean, value: () -> T, recallFunctionWithValue: (value: T) -> Unit) {
    this.context = context
    this.canCancel = canCancel
    this.functionPara = value
    this.recallFunctionWithFunction = recallFunctionWithValue

}

8/6 更新可变参数问题

我正在做一些高级的事情。我只是将它发布在完整的代码中。 如果我不使用 vararg ,则

EasyDialog<Observable<Any>,LiveData<Boolean>>(ctx, true,viewModel!!::callGetTeammateListAPITEST,recallFunctionWithFunction = viewModel!!::callMultipleAPI).createNativeNetworkDialog2()

不投射as ((Observable&lt;Any&gt;)-&gt;LiveData&lt;Boolean&gt;) .但是 callMuipleApi 接收 vararg 参数,我必须将其转换为 ((Observable)->LiveData) 但我没有显示任何错误,但未调用函数 callmuipleapi 和 callgetteammateslist 。 谁能帮忙?

视图模型

fun callMultipleAPI( vararg  observable: Observable<Any>):LiveData<Boolean>{
    if(progressDialogData==null){
        progressDialogData= MutableLiveData()
    }
    progressDialogData?.setValue(true)
    repo.callMultipleAPI<Any>(*observable, observer = RYEasyObserver(object : RyObserverSingleStatusListener<List<Any>> {
        override fun onNext(g: List<Any>) {
            Log.d("test",g.toString())
            for(model in g){
                when(model){
                    is GetTeammateListModel ->{setCallGetTeammateListResponse(model)}
                    is GetTeamListModel ->{setCallGetTeamListResponse(model)}
                    is GetMessageSumModel->{setCallGetMessageSumResponse(model)}
                    is GetCallModel->{setCallGetResponse(model)}
                }
            }
            progressDialogData?.setValue(false)
        }


        override fun onError() {
            progressDialogData?.setValue(false)
        }

    },true))
    return progressDialogData!!
}

片段

EasyDialog<Observable<Any>,LiveData<Boolean>>(ctx, true,viewModel!!::callGetTeammateListAPITEST,recallFunctionWithFunction = viewModel!!::callMultipleAPI as ((Observable<Any>)->LiveData<Boolean>)).createNativeNetworkDialog2()

EasyDialog

class EasyDialog<T,V> {
var canCancel: Boolean = true
var recallFunction: (() -> T)? = null
var recallFunctionWithValue: ((value: T) -> Unit)? = null
var context: Context? = null
var value: T? = null
var functionPara :(()->T)? = null
var recallFunctionWithFunction:((T) -> V)? = null



    constructor(
    context: Context?, canCancel: Boolean, value: ()->T, recallFunctionWithFunction:  (T) -> V  ){
    this.context = context
    this.canCancel = canCancel
    this.functionPara = value
    this.recallFunctionWithFunction = recallFunctionWithFunction
}
    fun createNativeNetworkDialog2() {
    val builder = AlertDialog.Builder(context)
    if (!canCancel) {
        builder.setCancelable(false)
    } else {
        builder.setNegativeButton(context?.resources?.getString(R.string.gloda_cancel)) { dialogInterface, id -> }
    }
    builder.setMessage(context?.resources?.getString(R.string.global_network_error))
    builder.setPositiveButton(context?.resources?.getString(R.string.global_retry)) { dialog, id ->
        recallFunction?.invoke()
        value?.let { it1 -> recallFunctionWithValue?.invoke(it1) }
        //functionPara?.let { it2->recallFunctionWithFunction?.invoke(it2) }
        functionPara?.let{ functionPara->{ recallFunctionWithFunction?.let {
                recallFunctionWithFunction-> compose<T,V>(recallFunctionWithFunction  ,functionPara).invoke()
        }}}
    }

    val dialog = builder.create()
    dialog.show()
}
    fun <T, V> compose( f: (T) -> V,    g:() -> T ): () -> V {
            return {  f(g()) }
}

【问题讨论】:

  • 需要查看每个类的第一行,以了解如何定义泛型类型以及如何定义主构造函数(如果有)。语法错误说明了什么?
  • 这个recallFunctionWithValue: (value: ()-&gt;T) -&gt; Unit 可能给出了错误。函数类型中不能有名称。你可能想要的是(() -&gt; T) -&gt; Unit 或类似的东西
  • 我已经更新了错误信息并清楚地显示了声明。
  • @user,这不是真的。您可以命名函数类型参数。
  • 我还是不知道你的错误在哪里。您在尝试调用构造函数时是否收到错误,或者它在您的构造函数定义中?错误标记在哪一行? this.recallFunctionWithFunction = recallFunctionWithValue 行,因为名称不匹配,但您实际上确实有一个名称匹配的参数 recallFunctionWithValue。

标签: generics kotlin lambda


【解决方案1】:

最后一个构造函数参数是

(() -> T) -> Unit

根据您为第三个构造函数参数传递的内容,T 被推断为Observable&lt;Any&gt;?。所以它期待一个

(() -> Observable<Any>?) -> Unit

但testRefOutside 是

 Observable<Any>? -> Unit

我猜你可能不是想通过将函数的输入设为另一个函数来定义三阶函数。

【讨论】:

  • 这取决于您使用这些功能的目的。这个类看起来很复杂,所以我不能仅仅通过查看来判断,但可能你想将最后一个构造函数参数类型更改为T -&gt; Unit,并对你分配给它的任何属性执行相同的操作。
  • 通过在主构造函数中定义属性并尽可能避免空值和读写vars,您的类会简单得多。
  • 我想将一个函数返回一个 observable 作为参数传递给另一个函数。在这种情况下,我想将 testRefInside 作为参数放入 testRefOutside。但是,我仍然不知道该怎么做。
  • value?.let { it1 -> recallFunctionWithValue?.invoke(it1) } 原始参数只有 T 类型,它可以工作!!但我想这样做,functionPara?.let { it1 -> recallFunctionWithFunction?.invoke(it1) }
  • 我已经更新了新问题,有人可以帮忙吗?我解决了 testRefOuside 和 inside 的问题,但高级问题是关于 vararg 参数
猜你喜欢
  • 1970-01-01
  • 2019-11-11
  • 2023-02-17
  • 1970-01-01
  • 2018-02-26
  • 2022-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多