2016-12-19 39 views
2

我扩展抽象类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方法显示了一个错误:

'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

为什么同样THI ng不会发生到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); 
     } 
    } 
} 

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

+0

您的意思是: 公共抽象类的适配器扩展RecyclerView.Adapter { –

+0

如果更改ViewHolder对于适配器,是的,我注意到并改变了它,但是谢谢你让我知道:) – LeonardoSibela

+0

不,我的意思是你将类型参数放入类派生签名,将“VH”传递给扩展部分。 –

回答

1

问题是你没有将你自己的抽象类的参数传播到链的顶端;你正在做:

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。

为什么其中一种方法“工作”而另一种方法没有,你可能会问?

嗯,那是因为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 a = new Pig(); 
// ... 
a.eat(wheat); // ?? 

会发生什么?正如你所看到的,通过参数你可以更通用,但不能更具体。对于返回类型,您可以更具体,但不是更通用。因为父母合同要求你收到A并返回B.如果你想收到多于A或返回少于B,没关系,这是你的电话。但是你必须至少得到A,并且最多返回B.这就是OOP的工作原理。

所以你的问题只是伪装仿制药,但它的广泛得多;)

+0

我并不知道返回和参数类型之间的差异,但是现在总是有意义的你解释一下。事实证明,这与泛型无关,但通常是OOP。 – LeonardoSibela

相关问题