1

我已经定义了以下具有两种泛型类型的基类,并使用了两层深度(因为缺少更好的短语)。这是我的用例。

abstract class BasePresenter<out M, out V> {
    var model: M? = null

    var view: WeakReference<V>? = null

    fun setM(model: M?): Unit {
        this.model = model

        if (setupDone()) {
            updateView()
        }
    }

    fun bindView(view: V) {
        this.view = WeakReference(view)
    }

    fun unbindView() {
        this.view = null
    }

    abstract fun updateView()

    fun view(): V? {
        return if (view == null) null else view?.get()
    }

    fun setupDone(): Boolean {
        return view() != null && model != null
    }
}

我正在使用它来扩展它

open class VenueListPresenter: BasePresenter<Venue, VenueView>()  {...}

正如预期的那样工作正常,但是当我尝试VenuListPresenter在不同的类中使用作为类型参数时遇到了问题。

open class VenuesViewHolder(itemView: View): MvpViewHolder<VenueListPresenter>(itemView) {

这给了我一个错误,指出预期的参数MvpViewHolder是 BasePresenter,并且找到的是VenueListPresenter. 我VenueListPresenter扩展了BasePresenter<Venue, VenueView>whereVenue并且VenueView是类型Any?,因为默认情况下它们扩展它。那么为什么它不起作用呢?

MvpViewHolder 是这样定义的

abstract class MvpViewHolder<P>(itemView: View) : RecyclerView.ViewHolder(itemView) where P : BasePresenter<Any?, Any?>
4

1 回答 1

3

您需要为out泛型参数添加变化,BasePresenter以便类似BasePresenter<Venue, VenueView>的类型成为BasePresenter<Any?, Any?>.

abstract class BasePresenter<out M, out V>

作为一个简短的解释,out关键字指定协方差,例如,如果你有一个类YourClass<out T>,它意味着 whenA是 的子类型B,thenYourClass<A>也是 的子类型YourClass<B>

在docs中查看有关 Kotlin 泛型和方差的更多详细信息。


根据以下评论进行编辑:

如果您无法进行上述更改,则可以在类中使用use site varianceMvpViewHolder来接受其类型参数中BasePresenter具有任何子类型的子类型:Any?

abstract class MvpViewHolder<P>(itemView: View) : RecyclerView.ViewHolder(itemView) 
        where P : BasePresenter<out Any?, out Any?>

你可以用星形投影做同样的事情(在这种情况下只是不同的语法):

abstract class MvpViewHolder<P>(itemView: View) : RecyclerView.ViewHolder(itemView) 
        where P : BasePresenter<*, *>

在这两种情况下,任何 typeVM从 a 返回的P内容都是 type Any?,您将无法将VorM实例传递给 的方法P。如果您需要能够做到这一点,您可以考虑添加更多通用参数:

abstract class MvpViewHolder<P, M, V>(itemView: View) : RecyclerView.ViewHolder(itemView)
        where P : BasePresenter<M, V>
于 2017-11-01T18:02:25.323 回答