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

时间:2016-12-19 16:17:18

标签: java android generics android-adapter

我正在扩展抽象类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方法显示上面的错误?

1 个答案:

答案 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的工作方式。

所以你的问题只是伪装成泛型,但它的范围要大得多;)