在Kotlin中使用受约束的泛型实现抽象类

时间:2019-11-28 11:36:42

标签: generics kotlin

致力于Kotlin 1.3.61

具有此代码:

data['tags'] = data['tags'].apply(lambda x : ",".join(re.findall("Up\d?_\S*(?=,)", x)) if re.findall("Up\d?_\S*(?=,)", x) else x )

并尝试实施

abstract class ResourceObserver<T> : Observer<T> where T : Resource<T> {
    override fun onChanged(t: T) {
        when (t.status) {
            Status.LOADING -> { ... }
            Status.ERROR -> { ... }
            Status.SUCCESS -> { onSuccess(t.data) }
        }
    }

    abstract fun onSuccess(data: T?)
}

编译器(在这种情况下为Android Studio)给了我这个错误:

private val foo = object : ResourceObserver<Resource<Bar>> {
    override fun onSuccess(data: Bar?) {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
}

我明显错误的代码有什么问题?

2 个答案:

答案 0 :(得分:2)

约束where T : Resource<T>确实要求您为T使用的任何类型参数也必须为Resource<T>(用类型本身代替T)。

根据此约束,将检查您为实现T := Resource<Bar>提供的type参数是否为Resource<T> ≡ Resource<Resource<Bar>>,并且此检查失败。

要使此约束和子类型起作用,Bar必须是Resource<Bar>的子类型(实现)。

您真的需要T成为具有相同Reosurce<T>T 吗?如果您使用带有star-projection T : Resource<*>的上限或添加另一个类型参数(如下所示),是否可以解决您的问题?

abstract class ResourceObserver<T, R> : Observer<T> where T : Resource<R> { ... }

private val foo = object : ResourceObserver<Resource<Bar>, Bar> { ... }

答案 1 :(得分:1)

这看起来像是尝试使用F-bounded polymorphism。要使其正常工作,您需要

  1. 使Bar扩展Resource<Bar>;

  2. 使用private val foo = object : ResourceObserver<Bar> { ... }代替<Resource<Bar>>

通常Resource本身将具有类似的约束条件

class Resource<T : Resource<T>>

因此,如果您忘记做1 Bar,则不会编译。