如何在 Kotlin 中创建一个以泛型函数作为参数的泛型函数?
How do I make a generic function with generic function as parameter in Kotlin?
我有大约 20 个文件,看起来像上图中的红色和蓝色部分,现在我想添加
private val requestDataSource: RequestDataSource
参数 (绿线 15) 并调用 requestDataSource.post()
(绿线 20) 给他们。
我试图创建一个带有自定义参数 P、自定义 return 类型 RET 和函数参数的通用函数,这样我就可以像在 sendEz
函数中那样使用它,但是它不工作。
函数参数出错:
类型不匹配。必需:(TypeVariable(P)) → ApiRequestResponse
发现:布尔
预计函数调用 'send(...)'
我不明白,我不想在第 30m 行调用它,同时看起来它被视为被调用,因为找到的参数是布尔值(return 类型service.sen(emnail)
) 但我不会在那里调用它...
这可以实现吗?如果是,怎么做?
代码在这里:
class EmailDataSource @Inject constructor(
private val dao: EmailDao,
private val service: EmailService,
private val requestDataSource: RequestDataSource,
): BaseDataSource<EmailModel, EmailDataModel>(dao) {
suspend fun send(email: EmailModel): ApiRequestResponse<Boolean> {
return try {
val response = service.send(email)
requestDataSource.post()
ApiRequestResponse.Success(response)
} catch (e: Throwable) {
val ioe = IOException("Error sending email", e)
Timber.w(ioe)
ApiRequestResponse.Error(ioe)
}
}
suspend fun sendEz(email: EmailModel): ApiRequestResponse<Boolean> {
return call<EmailModel, Boolean>(service.send, email, "Error sending email")
}
suspend fun <P: Any, RET: Any> call(
function: (parameter: P) -> ApiRequestResponse<RET>,
parameter: P,
error: String = "Error making the request"
): ApiRequestResponse<RET> {
return try {
val response = function(parameter)
requestDataSource.post()
response
} catch (e: Throwable) {
val ioe = IOException(error, e)
Timber.w(ioe)
ApiRequestResponse.Error(ioe)
}
}
}
解决方案:
protected suspend fun <P: Any, RET: Any> call(
function: KSuspendFunction1<P, RET>,
parameter: P,
error: String = "Error making the request"
): ApiRequestResponse<RET> {
val result = function(parameter) // call the function
}
/** And call it like this */
suspend fun get(param: String, param2: Boolean): ApiRequestResponse<WHAT service::get RETURNS> {
return call(service::get, param, param2, "Error message")
}
/** Where service is the retrofit interface */
@GET("Endpoint/{date}/{includeStops}")
suspend fun get(
@Path("date") date: String,
@Path("stops") stops: Boolean
): List<Model>
A .
是调用它的语法。 ::
仅用于传递对函数的引用。
所以试着用 service::send
代替 service.send
我有大约 20 个文件,看起来像上图中的红色和蓝色部分,现在我想添加
private val requestDataSource: RequestDataSource
参数 (绿线 15) 并调用 requestDataSource.post()
(绿线 20) 给他们。
我试图创建一个带有自定义参数 P、自定义 return 类型 RET 和函数参数的通用函数,这样我就可以像在 sendEz
函数中那样使用它,但是它不工作。
函数参数出错:
类型不匹配。必需:(TypeVariable(P)) → ApiRequestResponse
我不明白,我不想在第 30m 行调用它,同时看起来它被视为被调用,因为找到的参数是布尔值(return 类型service.sen(emnail)
) 但我不会在那里调用它...
这可以实现吗?如果是,怎么做?
代码在这里:
class EmailDataSource @Inject constructor(
private val dao: EmailDao,
private val service: EmailService,
private val requestDataSource: RequestDataSource,
): BaseDataSource<EmailModel, EmailDataModel>(dao) {
suspend fun send(email: EmailModel): ApiRequestResponse<Boolean> {
return try {
val response = service.send(email)
requestDataSource.post()
ApiRequestResponse.Success(response)
} catch (e: Throwable) {
val ioe = IOException("Error sending email", e)
Timber.w(ioe)
ApiRequestResponse.Error(ioe)
}
}
suspend fun sendEz(email: EmailModel): ApiRequestResponse<Boolean> {
return call<EmailModel, Boolean>(service.send, email, "Error sending email")
}
suspend fun <P: Any, RET: Any> call(
function: (parameter: P) -> ApiRequestResponse<RET>,
parameter: P,
error: String = "Error making the request"
): ApiRequestResponse<RET> {
return try {
val response = function(parameter)
requestDataSource.post()
response
} catch (e: Throwable) {
val ioe = IOException(error, e)
Timber.w(ioe)
ApiRequestResponse.Error(ioe)
}
}
}
解决方案:
protected suspend fun <P: Any, RET: Any> call(
function: KSuspendFunction1<P, RET>,
parameter: P,
error: String = "Error making the request"
): ApiRequestResponse<RET> {
val result = function(parameter) // call the function
}
/** And call it like this */
suspend fun get(param: String, param2: Boolean): ApiRequestResponse<WHAT service::get RETURNS> {
return call(service::get, param, param2, "Error message")
}
/** Where service is the retrofit interface */
@GET("Endpoint/{date}/{includeStops}")
suspend fun get(
@Path("date") date: String,
@Path("stops") stops: Boolean
): List<Model>
A .
是调用它的语法。 ::
仅用于传递对函数的引用。
所以试着用 service::send
代替 service.send