使用泛型类型不匹配
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>
。如果您在方法上声明泛型,则每次方法调用的实际类型可能不同。
我在理解泛型时遇到了问题,我在这里找不到答案。
这是问题所在:
我有一个抽象 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>
。如果您在方法上声明泛型,则每次方法调用的实际类型可能不同。