我的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>,其中TDataTypeB或其子类型。这意味着您将需要在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。然后,这将更改myAdapterDataTypeA上的类型参数部分。我对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/

10-12 00:30