Home > Back-end >  How to override kotlin interface inside companion object
How to override kotlin interface inside companion object

Time:11-02

I'm generating code with open-api codegen using --library jvm-retrofit2 and coroutines=true. I'm writing an Android kotlin client library that consumes a REST API. I don't want to offer the users of my library only the raw Retrofit Response so I want to override it like this:

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()
  ...
}

This is only a draft, but as you can see more than ugly. The problem is if I don't extend the class from the generated Retrofit Interfaces (RetrofitBooksApi) I won't see that there were new methods added to the interfaces when I someday rerun the code generation from the REST API Spec, so I though maybe I could extend from the interface and override them, but now I have the problem that I need to call the overriden functions inside the companion block and I'm not sure about the cons of instantiating the class in each function to be able to call the overriden functions outside and if I can let the function name be identical inside and outside. The second problem is I cannot really change the return type of the overriden function to my custom response object, then it doesn't make sense to override the function in the first place, right?

CodePudding user response:

If I understand your case correctly, then you can make it much simpler by just creating a singleton that implements RetrofitBooksApi:

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

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

You should be able to override the return type as long as the new one is a subtype of the original one. If it is not a subtype then your ApiBook has really a different API than RetrofitBooksApi and I believe you need to keep them in sync manually. Alternative would be to write a compiler plugin. I don't know if Retrofit helps with such cases in any way.

  • Related