使用泛型类型不匹配

Type mismatch using generics

我在理解泛型时遇到了问题,我在这里找不到答案。

这是问题所在:

我有一个抽象 class,它被认为是几个视图模型的父 class。想法是,将根据来自不同视图模型的数据创建一个视图。 而且我想基于相同的方法绘制它,只是使用不同的类型。

此外,我不想要 return 类型,我想触发一些回调。

摘要如下:

package foo.bar.ui.app.user_profile.view_model


abstract class UserDefaultsGenericViewModel : BaseViewModel() {
    abstract fun <P> getData(
        data: (P) -> Unit,
        error: (Result.Error) -> Unit
    )
} 

然后一个 ViewModel 的例子是这样的:

package foo.bar.ui.app.user_profile.view_model


@HiltViewModel
class StopViewModel @Inject constructor(
    private val getStopsByRouteUseCase: ParamsUseCase<RouteParams, Stops>
) : UserDefaultsGenericViewModel() {

    var stopId = ""
    override fun <Stops> getData(data: (Stops) -> Unit, error: (Result.Error) -> Unit) {
        viewModelScope.launch {
            when (val resultStops = getStopsByRouteUseCase.invoke(RouteParams(stopId, Direction.ToWork))) {
                is Result.Success -> {
                    data.invoke(resultStops.value)
                }
                is Result.Error -> Log.e("TAG", "bar")
            }
        }
    }
}

问题出在这一行: data.invoke(resultStops.value)

我得到:

Type mismatch: inferred type is foo.bar.onboarding.Stops but Stops#1 (type parameter of foo.bar.ui.app.user_profile.view_model.StopViewModel.getData) was expected

我做错了什么?

您正在使用通用方法,但您似乎需要通用方法 class/interface。

在您的 override fun <Stops> getData 中,Stops 是类型参数的任意名称,而不是您似乎想要的实际 Stops 类型。您可能想要的是以下内容:

// note the <P> at the class level
abstract class UserDefaultsGenericViewModel<P> : BaseViewModel() {

    // no <P> here after the fun keyword
    abstract fun getData(
        data: (P) -> Unit,
        error: (Result.Error) -> Unit
    )
}

@HiltViewModel
class StopViewModel @Inject constructor(
    private val getStopsByRouteUseCase: ParamsUseCase<RouteParams, Stops>
) : UserDefaultsGenericViewModel<Stops>() { // note the <Stops> type argument here

    ...
}

此处 <P> 位于 class 声明中,因此 class 的每个实例都会确定一次 <P>。如果您在方法上声明泛型,则每次方法调用的实际类型可能不同。