我的Android应用程序中有一个适配器,我想使其通用。
适配器基本上是这样的:
public class myAdapter extends FragmentStatePagerAdapter {
DataTypaA myFragment;
DataTypeB data;
DataTypeC items;
public myAdapter(FragmentManager fm, DataTypaA fragment) {
data = new SparseArray<DataTypeB>();
myFragment = fragment;
items = myFragment.getData();
}
public DataTypeB getItem(int position) {
return data.get(position);
}
@Override
public int getCount() {
return items.getList().size();
}
public void setData () {
items = myFragment.getItems () //getItems return DataTypeC
data.setTheData (items)
}
}
我将其更改为通用
public class myAdapter <A,B,C> extends FragmentStatePagerAdapter {
A myFragment;
B data;
C items;
public myAdapter(FragmentManager fm, A fragment) {
data = new SparseArray<B>();
myFragment = fragment;
items = (C) myFragment.getData();
}
public B getItem(int position) {
return data.get(position);
}
@Override
public int getCount() {
return items.getList().size();
}
public void setData () {
items = myFragment.getItems () //getItems return DataTypeC
data.setTheData (items)
}
}
但是我遇到了不同的错误,当方法应该获取
DataTypeC
参数并向其传递实际上是C
类型的参数类型data.setTheData (items)
(DataTypeC
)时,编译器建议将C
转换为类型DataTypeC
。在getCount()
中,我也有错误建议将items
转换为DataTypeC
。例如,当我尝试覆盖getItem时,我会出错,但是当我使用其他名称创建相同的方法时,它将编译。
//Error - "The return type is incompatible with FragmentStatePagerAdapter.getItem(int)"
@Override
public B getItem(int position) {
return (B) data.get(position);
}
//compiles
public B getItemTest(int position) {
return data.get(position);
}
任何想法如何解决它,使其成为100%通用的?
添加:在您回答之后,我将其更改为支持通用类型的返回:
public class TypeA <T> {
private T mData;
public T getData() { return mData;; }
}
public class myAdapter <A,B,C> extends FragmentStatePagerAdapter {
A myFragment;
B data;
C items;
public myAdapter(FragmentManager fm, A fragment) {
data = new SparseArray<B>();
myFragment = fragment;
items = myFragment.getData(); //Error - The method getData() is undefined for the type T
}
}
我收到编译错误...
当我运行它时,
<T>
和<C>
是相同的类型。 最佳答案
第一个问题是您的非通用代码无法编译。您有一个字段DataTypeB data;
,然后将其分配给SparseArray<DataTypeB>
。另外,setData
根本不编译。
忽略此...您已经声明了类型参数A, B, C
并更改了实例字段类型,但是您仍然尝试在构造函数中将DataTypaA
分配给A myFragment
,并且将SparseArray<DataTypeB>
分配给B data
。当您将代码迁移到泛型时,您需要像重构那样进行处理-一次仅一步。
例如,通过现在进入,您可以查看items = (C)myFragment.getData()
。由于fragment
仍然是DataTypaA
类型,因此大概它的getData()
方法不会返回泛型类型。某些事情将不得不改变。
您有很多工作要做,所以重复我自己-将此视为重构练习,然后逐步进行。
获取您的非泛型类型进行编译。
将myFragment
更改为A myFragment
并声明类型参数<A extends DataTypaA
。在继续之前,请查看需要做什么才能使其编译。
现在来看将data
移为SparseArray<B> data
。大概需要一个SparseArray<T>
,其中T
是DataTypeB
或其子类型。这意味着您将需要在B
上基于通配符的绑定。类似于B extends SparseArray<? extends DataTypeB>
现在查看items
。您知道它是从新的通用类型变量A extends DataTypeA
返回的,因此DataTypeA
需要是通用的,并且具有从getData
返回的通用类型变量。假设使用DataTypeA<T extends DataTypeC>
将其声明为public T getData() { ... }
。
因此,现在您的类型参数部分更改为:
class DataTypaA<T extends DataTypeC>
...
class myAdapter <A extends DataTypaA<C>,
B extends SparseArray<? extends DataTypeB>,
C extends DataTypeC>
extends FragmentStatePagerAdapter {
A myFragment;
SparseArray<B> data;
C items;
...
鉴于您已发布的代码,对此很难走得太远-并非所有的类和信息都在那儿,但这是您必须遵循的过程。
例如:您可能不需要将
C
限制为DataTypeC
。然后,这将更改myAdapter
和DataTypeA
上的类型参数部分。我对SparseArray<B>
的假设可能也不正确-但您的代码目前无法编译,因此我无法告知。最终的实现可能类似于:class myAdapter <A extends DataTypaA<C>,
B extends SparseArray<? extends DataTypeB,
? extends DataTypeC>,
C extends DataTypeC>
extends FragmentStatePagerAdapter {
A myFragment;
SparseArray<B, C> data;
C items;
public myAdapter(FragmentManager fm, A fragment) {
data = new SparseArray<B, C>();
myFragment = fragment;
items = myFragment.getData();
}
public B getItem(int position) {
return data.get(position);
}
@Override
public int getCount() {
return items.getList().size();
}
public void setData () {
items = myFragment.getItems (); //getItems return DataTypeC
data.setTheData(items);
}
}
为此,我使用了伪类:
class DataTypaA<T extends DataTypeC> {
public T getData() { return null; }
public T getItems() { return null; }
}
class SparseArray<T, S> {
public T get(int foo) { return null; }
public void setTheData(S items){}
}
class DataTypeB {
}
class DataTypeC {
// do NOT use the raw type List - just done to get your code to compile
public List getList() { return null; }
}
abstract class FragmentStatePagerAdapter {
public abstract int getCount();
}
class FragmentManager {
}
关于java - 转换自定义适配器以在Java中使用泛型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28269395/