我正在扩展抽象类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
}
进入另一个抽象类:
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
方法显示错误:
“com.leonardo.endlessrecycerviewwithsqlitepagination.adapter.ViewHolder”中的“onBindViewHolder(VH,int)”与“android.support.v7.widget.RecyclerView.Adapter”中的“onBindViewHolder(VH,int)”冲突;两种方法都有相同的擦除,但都没有覆盖其他方法
为什么同样的事情不会发生在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);
}
}
}
为什么现在BOTH方法显示上面的错误?
答案 0 :(得分:3)
问题是你没有传播自己的抽象类&#39;参数下降到链的顶部;你在做什么:
public abstract class Adapter<VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<RecyclerView.ViewHolder>
为了减少这种混乱,让我们调用适配器的通用参数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。
为什么其中一种方法有效?&#39;另一个没有,你可能会问?
嗯,这是因为OOP的工作方式。观察您的VH2被定义为扩展RecyclerView.ViewHolder。所以VH2 是 RecyclerView.ViewHolder。
因此,如果父方法返回 VH,您可以在继承中指定它返回的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() { ... }
}
没关系!屠宰场总是返回动物,因为农场需要,因为猪是动物!
现在让我们考虑另一种方法:
public abstract void onBindViewHolder(VH viewHolder, int position);
此处,父级要求参数的类型为VH = ViewHolder。在这种情况下,你不能在孩子身上放置更具体的东西!父请求每个孩子都知道如何处理每个可能的ViewHolder,而不仅仅是那些扩展ViewHolder的VH2。在这里,您可以更加通用,但不能更具体!例如:
public abstract class Animal {
abstract void eat(Food f);
}
public class Pig extends Animal {
@Override
void eat(Carrot c) { ... }
}
这不会奏效!通过扩展Animal,您必须遵守其要求!动物要求每只动物必须吃一种可以吃任何食物的食物,而不仅仅是胡萝卜。想象一下,我这样做了:
Animal a = new Pig();
// ...
a.eat(wheat); // ??
会发生什么?正如您所看到的,使用参数可以更通用,但不能更具体。对于返回类型,您可以更具体,但不是更通用。因为父母合同要求你收到A并返回B.如果你想收到的金额超过A,或者收到的金额低于B,那就没问题了,这就是你的电话。但是你必须至少得到A,并且最多返回B.这就是OOP的工作方式。
所以你的问题只是伪装成泛型,但它的范围要大得多;)