在 Java 中转换自定义适配器以使用泛型
Convert custom adapter to use generics in Java
我的 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% 通用的任何想法?
ADDED:在你回答后我将其更改为支持通用类型的 return:
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>
是同一类型。
当 "genericizing" class 时,您应该将泛型类型的所有实例替换为它们的泛型:DataTypaA
变为 A
,等等
您还需要确保您在其他对象(如 fragment.getData()
)上调用的方法中的 return 类型与泛型兼容。为此,您可以指示泛型类型扩展了一个已知的 class:
public class MyAdapter<A extends MyData,B extends MyData,...>
Java Tutorial on generics 可以提供更多信息。
第一个问题是您的非通用代码无法编译。您有一个字段 DataTypeB data;
,然后您将 SparseArray<DataTypeB>
分配给该字段。此外,setData
根本无法编译。
忽略这个...您已经声明了类型参数 A, B, C
并更改了您的实例字段类型,但您仍然尝试在构造函数中将 DataTypaA
分配给 A myFragment
,并且SparseArray<DataTypeB>
到 B data
。当您将代码迁移到泛型时,您需要像重构一样处理它 - 一次一个步骤。
例如,像现在这样深入研究 items = (C)myFragment.getData()
。由于 fragment
仍然是 DataTypaA
类型,因此可以推测它的 getData()
方法不是 return 泛型类型。有些事情将不得不改变。
你有很多工作要做,所以重复一遍 - 将此视为重构练习并逐步进行。
- 获取要编译的非泛型类型。
- 将
myFragment
更改为 A myFragment
并声明类型参数 <A extends DataTypaA
。在继续之前看看需要做什么才能编译它。
- 现在看看移动
data
成为 SparseArray<B> data
。据推测,这需要一个 SparseArray<T>
,其中 T
是一个 DataTypeB
,或其子类型。这意味着您将需要在 B
上进行基于通配符的绑定。像 B extends SparseArray<? extends DataTypeB>
- 现在看
items
。您知道它是从您的新泛型类型变量 A extends DataTypeA
中 return 编辑的,因此 DataTypeA
需要是泛型的并且具有从 getData
中编辑的泛型类型变量 return ].假设它被声明为 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 {
}
我的 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% 通用的任何想法?
ADDED:在你回答后我将其更改为支持通用类型的 return:
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>
是同一类型。
当 "genericizing" class 时,您应该将泛型类型的所有实例替换为它们的泛型:DataTypaA
变为 A
,等等
您还需要确保您在其他对象(如 fragment.getData()
)上调用的方法中的 return 类型与泛型兼容。为此,您可以指示泛型类型扩展了一个已知的 class:
public class MyAdapter<A extends MyData,B extends MyData,...>
Java Tutorial on generics 可以提供更多信息。
第一个问题是您的非通用代码无法编译。您有一个字段 DataTypeB data;
,然后您将 SparseArray<DataTypeB>
分配给该字段。此外,setData
根本无法编译。
忽略这个...您已经声明了类型参数 A, B, C
并更改了您的实例字段类型,但您仍然尝试在构造函数中将 DataTypaA
分配给 A myFragment
,并且SparseArray<DataTypeB>
到 B data
。当您将代码迁移到泛型时,您需要像重构一样处理它 - 一次一个步骤。
例如,像现在这样深入研究 items = (C)myFragment.getData()
。由于 fragment
仍然是 DataTypaA
类型,因此可以推测它的 getData()
方法不是 return 泛型类型。有些事情将不得不改变。
你有很多工作要做,所以重复一遍 - 将此视为重构练习并逐步进行。
- 获取要编译的非泛型类型。
- 将
myFragment
更改为A myFragment
并声明类型参数<A extends DataTypaA
。在继续之前看看需要做什么才能编译它。 - 现在看看移动
data
成为SparseArray<B> data
。据推测,这需要一个SparseArray<T>
,其中T
是一个DataTypeB
,或其子类型。这意味着您将需要在B
上进行基于通配符的绑定。像B extends SparseArray<? extends DataTypeB>
- 现在看
items
。您知道它是从您的新泛型类型变量A extends DataTypeA
中 return 编辑的,因此DataTypeA
需要是泛型的并且具有从getData
中编辑的泛型类型变量 return ].假设它被声明为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 {
}