如何覆盖伴随对象内的 kotlin 接口
How to override kotlin interface inside companion object
我使用 --library jvm-retrofit2 和 coroutines=true 使用 open-api codegen 生成代码。我正在编写一个使用 REST API 的 Android kotlin 客户端库。我不想只向我的库的用户提供原始改造响应,所以我想像这样覆盖它:
open class ApiBook : RetrofitBooksApi {
companion object {
private fun getRetrofitService(): RetrofitBooksApi {
val apiClient = ApiClient()
return apiClient.createService(RetrofitBooksApi::class.java)
}
suspend fun getBooksList(...): MyCustomResponse<List<Book>> {
return getBooksList(...)
}
}
override suspend fun getBooksList(
...
): MyCustomResponse<List<Book>> {
// Custom implementation, handling of errors, nulls, etc. and passing a
// MyCustomResponse.Success or MyCustomResponse.Error object back.
}
}
MainActivity {
...
val response = ApiBook.getBooksList()
...
}
这只是一个草稿,但如你所见,丑陋不止。问题是,如果我不从生成的 Retrofit 接口 (RetrofitBooksApi) 扩展 class,当我有一天从 REST [=21] 重新运行代码生成时,我将看不到有新方法添加到接口中=] 规范,所以我虽然也许我可以从接口扩展并覆盖它们,但现在我遇到了一个问题,我需要在伴随块中调用覆盖的函数,我不确定实例化 class 在每个函数中,以便能够在外部调用覆盖的函数,如果我可以让函数名称在内部和外部相同。
第二个问题是我无法真正将覆盖函数的 return 类型更改为我的自定义响应对象,那么首先覆盖该函数就没有意义了,对吧?
如果我正确理解你的情况,那么你可以通过创建一个实现 RetrofitBooksApi
:
的单例来简化它
object ApiBook : RetrofitBooksApi {
override suspend fun getBooksList() { ... }
private fun getRetrofitService(): RetrofitBooksApi { ... }
}
MainActivity {
...
val response = ApiBook.getBooksList()
...
}
只要新类型是原始类型的子类型,您就应该能够覆盖 return 类型。如果它不是子类型,那么您的 ApiBook
与 RetrofitBooksApi
确实有不同的 API,我相信您需要手动使它们保持同步。另一种方法是编写一个编译器插件。我不知道 Retrofit 是否以任何方式帮助解决这种情况。
我使用 --library jvm-retrofit2 和 coroutines=true 使用 open-api codegen 生成代码。我正在编写一个使用 REST API 的 Android kotlin 客户端库。我不想只向我的库的用户提供原始改造响应,所以我想像这样覆盖它:
open class ApiBook : RetrofitBooksApi {
companion object {
private fun getRetrofitService(): RetrofitBooksApi {
val apiClient = ApiClient()
return apiClient.createService(RetrofitBooksApi::class.java)
}
suspend fun getBooksList(...): MyCustomResponse<List<Book>> {
return getBooksList(...)
}
}
override suspend fun getBooksList(
...
): MyCustomResponse<List<Book>> {
// Custom implementation, handling of errors, nulls, etc. and passing a
// MyCustomResponse.Success or MyCustomResponse.Error object back.
}
}
MainActivity {
...
val response = ApiBook.getBooksList()
...
}
这只是一个草稿,但如你所见,丑陋不止。问题是,如果我不从生成的 Retrofit 接口 (RetrofitBooksApi) 扩展 class,当我有一天从 REST [=21] 重新运行代码生成时,我将看不到有新方法添加到接口中=] 规范,所以我虽然也许我可以从接口扩展并覆盖它们,但现在我遇到了一个问题,我需要在伴随块中调用覆盖的函数,我不确定实例化 class 在每个函数中,以便能够在外部调用覆盖的函数,如果我可以让函数名称在内部和外部相同。 第二个问题是我无法真正将覆盖函数的 return 类型更改为我的自定义响应对象,那么首先覆盖该函数就没有意义了,对吧?
如果我正确理解你的情况,那么你可以通过创建一个实现 RetrofitBooksApi
:
object ApiBook : RetrofitBooksApi {
override suspend fun getBooksList() { ... }
private fun getRetrofitService(): RetrofitBooksApi { ... }
}
MainActivity {
...
val response = ApiBook.getBooksList()
...
}
只要新类型是原始类型的子类型,您就应该能够覆盖 return 类型。如果它不是子类型,那么您的 ApiBook
与 RetrofitBooksApi
确实有不同的 API,我相信您需要手动使它们保持同步。另一种方法是编写一个编译器插件。我不知道 Retrofit 是否以任何方式帮助解决这种情况。