具有相同的擦除,但都不会覆盖仅在一种情况下出现的其他警告

Have same erasure, yet neither overrides the other warning appearing in only ONE situation

我正在扩展摘要class RecyclerView.Adapter:

public static abstract class Adapter<VH extends ViewHolder> {
    public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

    public abstract void onBindViewHolder(VH holder, int position);

    // some more code
}

进入另一个摘要class:

public abstract class Adapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

    public abstract void onBindViewHolder(VH viewHolder, int position);

}

但是当我这样做时,只有 onBindViewHolder 方法显示错误:

'onBindViewHolder(VH, int)' in 'com.leonardo.endlessrecycerviewwithsqlitepagination.adapter.ViewHolder' clashes with 'onBindViewHolder(VH, int)' in 'android.support.v7.widget.RecyclerView.Adapter'; both methods have same erasure, yet neither overrides the other

为什么 onCreateViewHolder 方法没有发生同样的事情?

另一个问题是在这个场景中:

public abstract class Adapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<ViewHolder.CustomViewHolder> {

    public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

    public abstract void onBindViewHolder(VH holder, int position);

    static class CustomViewHolder extends RecyclerView.ViewHolder {

        public CustomViewHolder(View itemView) {
            super(itemView);
        }
    }
}

为什么现在两种方法都显示上面的错误?

问题是您没有将自己的抽象 class' 参数传播到链的顶部;你在做什么:

public abstract class Adapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder>

为了减少混淆,我们将 Adapter 的泛型参数称为 VH2;那么,我们有:

public abstract class Adapter<VH2 extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder>

public static abstract class Adapter<VH extends ViewHolder>

所以从RecyclerView.Adapter继承的方法必须是VH类型,而不是VH2!看到不同?在您的抽象实现中,VH = RecyclerView.ViewHolder。所以凡是有 VH 的地方,你现在必须用 RecyclerView.ViewHolder 而不是 VH2.

为什么其中一种方法 'work' 而另一种方法不行,您可能会问?

嗯,那是因为 OOP 的工作原理。观察您的 VH2 被定义为扩展 RecyclerView.ViewHolder。所以VH2RecyclerView.ViewHolder.

所以如果一个parent方法returns一个VH,你可以在你的继承中,指定 returns 是什么类型的 VH;在这种情况下,VH2 是一个 VH,因此您可以安全地执行以下操作:

public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);

举个例子:

public abstract class Farm {
    Animal abstract getAnimal();
}

public class Abattoir extends Farm {
    @Override
    Pig getAnimal() { ... }
}

没关系!根据农场的要求,屠宰场总是 return 动物,因为猪是动物!

现在让我们考虑另一种方法:

public abstract void onBindViewHolder(VH viewHolder, int position);

这里parent要求参数类型为VH = ViewHolder。在这种情况下,您不能在 child 中放置更具体的内容! parent 要求每个 child 知道如何处理每个可能的 ViewHolder,而不仅仅是那些扩展 ViewHolder 的 VH2。在这里你可以更通用,但不能更具体!例如:

public abstract class Animal {
    abstract void eat(Food f);
}

public class Pig extends Animal {
    @Override
    void eat(Carrot c) { ... }
}

这不行!通过扩展 Animal,您必须遵守它的要求! Animal要求每个动物都必须有一个eat方法,可以吃任何食物,而不仅仅是胡萝卜。想象一下我这样做了:

Animal a = new Pig();
// ...
a.eat(wheat); // ??

会发生什么?因此,正如您所见,使用参数可以更通用,但不能更具体。使用 return 类型,您可以更具体,但不能更通用。因为 parent 合同要求你收到 A 和 return B。如果你想收到比 A 多,或者 return 比 B 少,没关系,这是你的决定。但是你必须至少收到 A,并且 return 最多收到 B。这就是 OOP 的工作原理。

所以你的问题只是伪装成泛型,但范围更广;)