如何在伴随对象中覆盖 kotlin 接口

Posted

技术标签:

【中文标题】如何在伴随对象中覆盖 kotlin 接口【英文标题】:How to override kotlin interface inside companion object 【发布时间】:2021-12-15 22:13:43 【问题描述】:

我正在使用 --library jvm-retrofit2coroutines=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 Interfaces (RetrofitBooksApi) 扩展类,当我有一天从 REST API 规范重新运行代码生成时,我不会看到接口中添加了新方法,所以我想也许我可以从接口扩展并覆盖它们,但现在我有一个问题,我需要在伴随块中调用被覆盖的函数,我不确定在每个函数中实例化类以便能够调用的缺点外部覆盖函数,如果我可以让函数名称在内部和外部相同。 第二个问题是我不能真正将覆盖函数的返回类型更改为我的自定义响应对象,那么首先覆盖该函数没有意义,对吧?

【问题讨论】:

【参考方案1】:

如果我正确理解了你的情况,那么你可以通过创建一个实现 RetrofitBooksApi 的单例来简化它:

object ApiBook : RetrofitBooksApi 
    override suspend fun getBooksList()  ... 
    private fun getRetrofitService(): RetrofitBooksApi  ... 


MainActivity 
  ...
  val response = ApiBook.getBooksList()
  ...

只要新的返回类型是原始类型的子类型,您就应该能够覆盖返回类型。如果它不是子类型,那么您的 ApiBookRetrofitBooksApi 的 API 确实不同,我相信您需要手动保持它们同步。另一种方法是编写一个编译器插件。我不知道 Retrofit 是否对这种情况有任何帮助。

【讨论】:

以上是关于如何在伴随对象中覆盖 kotlin 接口的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Android+Kotlin 中 newStartIntent 的伴随对象?

启用 proguard 后无法访问 kotlin 类中使用的伴随对象

为什么Android + Kotlin中newStartIntent的伴随对象?

kotlin,如何使内部函数也能够在子类中被覆盖(在其他模块中)

如何在 Kotlin 中用继承的类覆盖方法?

在 Kotlin lambda 表达式中覆盖多个接口方法