繁体   English   中英

转换自定义适配器以在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参数并向其传递参数类型Cdata.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分配给DataTypaA中的A myFragment ,并将SparseArray<DataTypeB>分配给B data 当您将代码迁移到泛型时,您需要像重构那样进行处理-一次仅一步。

例如,通过现在进入,可以查看items = (C)myFragment.getData() 由于fragment仍然是DataTypaA类型, DataTypaA大概它的getData()方法不会返回泛型类型。 某些事情将不得不改变。

您有很多工作要做,所以重复我自己-将此视为重构练习,然后逐步进行。

  1. 获取您的非泛型类型进行编译。
  2. myFragment更改为A myFragment并声明类型参数<A extends DataTypaA 在继续之前,请查看需要做什么才能使其编译。
  3. 现在将移动data视为SparseArray<B> data 大概这需要SparseArray<T> ,其中TDataTypeB或其子类型。 这意味着您将需要在B上基于通配符的绑定。 B extends SparseArray<? extends DataTypeB>这样的东西B extends SparseArray<? extends DataTypeB> B extends SparseArray<? extends DataTypeB>
  4. 现在看一下items 您知道它是从新的通用类型变量A extends DataTypeA ,因此DataTypeA需要是通用的,并且具有从getData返回的通用类型变量。 假设它是使用public T getData() { ... }声明为DataTypeA<T extends DataTypeC>

因此,现在您的类型参数部分更改为:

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 {
}

当“泛化”类时,应将泛化类型的所有实例替换为其泛型: DataTypaA变为ADataTypaA

您还需要确保您在其他对象(例如fragment.getData() )上调用的方法的返回类型与泛型兼容。 为此,您可以指示泛型扩展了一个已知的类:

public class MyAdapter<A extends MyData,B extends MyData,...>

有关泛型Java教程可提供更多信息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM