我正在尝试创建一个定义单个方法的接口 . 该方法的参数类型必须是接口的类型参数,因为接口的实现将具有此参数的唯一实现 . 到目前为止很好,但问题是该参数还有一个与方法绑定的类型参数 . 我可以将类型的参数定义为类类型参数,它还有自己的类型参数,该参数与方法相关联吗?
换一种方式:
我正在尝试使用两个实现构建一个api客户端接口 . 每个客户端根据传递到 rxecute
函数的 Request<T>
对象进行api调用(RxJava执行,是的,我对这个名称感到非常自豪) .
我的问题是如何在界面中定义 rxecute
方法 . 让我列出一些示例代码(我的实际代码不是使用 impl
,不用担心) .
interface Request<T> // T is return type of the request
class RequestImpl<T>: Request<T> { // impl }
interface ApiClient<R : Request<*>> {
// R should somehow be of type Request<T>
fun <T> rxecute(request: R): Single<T>
}
class ApiClientImpl : ApiClient<RequestImpl<????>> {
override fun <T> rxecute(request: RequestImpl<T>): Single<T> = // impl
}
我希望能够像这样使用它:
val apiClient = ApiClientImpl()
apiClient.rxecute(RequestImpl<SomeClass>()).subscribe(someClassResult -> ...)
是否可以创建这样的界面,或者泛型不能像那样工作?
1 回答
不幸的是,Kotlin仿制药不能以这种方式操纵;类型参数
R
不能用作泛型类型本身(R<T>
),并且其上限在声明站点处是固定的,并且您只能使用类型参数R
作为单个上限(无法添加另一个,where Q : R, Q : Request<T>
不起作用) .您只能参数化具体类型,我想到的一个选项是recursive generics模式(它也用于Java) . 您可以将实现类型的另一个类型参数添加到
Request
,以使其成为interface Request<R, T>
. 这要求您将实现的类型添加到继承的类型声明:然后修改
ApiClient
:这里出现的一个不受欢迎的副作用是你需要将请求转换为RequestImpl:request请求作为RequestImpl .
并转换
ApiClientImpl
如下:这个解决方案看起来比你要求的更冗长,但递归泛型似乎是这种情况的常见解决方法,这需要比Java和Kotlin提供的更强大的类型系统 .
(runnable demo of the code in the answer)