java - 如何创建一个适用于两个不同对象的基类?

标签 java

我有两个类,PersonAdapterAnimalAdapter

这两个类几乎相同,因此我试图尽可能减少样板代码。

PersonAdapter 扩展自 RecyclerView.Adapter

AnimalAdapter 扩展自 RecyclerView.Adapter。 这两个类都实现了 Filterable 接口(interface)。

PersonAdapter 定义了一个从 Filter 扩展的内部类 PersonFilter

AnimalAdapter 定义了一个从 Filter 扩展的内部类 AnimalFilter

我想用某种通用类替换 PersonFilterAnimalFilter ,但我不知道如何替换,因为这些是两个类之间的差异:

PersonFilter 
    - works with a List<Person>
    - uses Person#getName() to make a string comparison

AnimalFilter 
    - works with a List<Animal>
    - uses Animal#getType() to make a string comparison

请快速浏览一下这两个类:

PersonAdapter

public class PersonAdapter extends RecyclerView.Adapter<PersonViewHolder> implements Filterable {
    private List<Person> persons;
    private PersonFilter personFilter;

    public PersonAdapter(List<Person> persons) {
        this.persons = persons;
    }

    ...

    @Override
    public Filter getFilter() {
        if(personFilter == null)
            personFilter = new PersonFilter(this, persons);
        return personFilter;
    }


    public static class PersonFilter extends Filter {
        private final PersonAdapter adapter;

        private final List<Person> originalList;

        private final List<Person> filteredList;

        private PersonFilter(PersonAdapter adapter, List<Person> originalList) {
            super();
            this.adapter = adapter;
            this.originalList = new LinkedList<>(originalList);
            this.filteredList = new ArrayList<>();
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            filteredList.clear();
            final FilterResults results = new FilterResults();

            if (constraint.length() == 0) {
                filteredList.addAll(originalList);
            } else {
                final String filterPattern = constraint.toString().toLowerCase().trim();

                for (final Person person : originalList) {
                    if (person.getName().toLowerCase().contains(filterPattern.toLowerCase())) {
                        filteredList.add(person);
                    }
                }
            }
            results.values = filteredList;
            results.count = filteredList.size();
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            adapter.persons.clear();
            adapter.persons.addAll((ArrayList<Person>) results.values);
            adapter.notifyDataSetChanged();
        }
    }
}

动物适配器

public class AnimalAdapter extends RecyclerView.Adapter<AnimalViewHolder> implements Filterable {
    private List<Animal> animals;
    private AnimalFilter animalFilter;

    public AnimalAdapter(List<Animal> animals) {
        this.animals = animals;
    }

    ...


    public static class AnimalFilter extends Filter {
        private final AnimalAdapter adapter;

        private final List<Animal> originalList;

        private final List<Animal> filteredList;

        private AnimalFilter(AnimalAdapter adapter, List<Animal> originalList) {
            super();
            this.adapter = adapter;
            this.originalList = new LinkedList<>(originalList);
            this.filteredList = new ArrayList<>();
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            filteredList.clear();
            final FilterResults results = new FilterResults();

            if (constraint.length() == 0) {
                filteredList.addAll(originalList);
            } else {
                final String filterPattern = constraint.toString().toLowerCase().trim();

                for (final Animal animal : originalList) {
                    if (animal.getType().toLowerCase().contains(filterPattern.toLowerCase())) {
                        filteredList.add(animal);
                    }
                }
            }
            results.values = filteredList;
            results.count = filteredList.size();
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            adapter.animals.clear();
            adapter.animals.addAll((ArrayList<Animal>) results.values);
            adapter.notifyDataSetChanged();
        }
    }
}

我应该如何创建一个通用的 Filter 子类,它既可以与 Animal 和 Person 对象一起使用,也可以被 PersonAdapter 和 AnimalAdapter 使用?

最佳答案

这是一个过滤器,它使用泛型和谓词从问题中提取两个过滤器。使用类似 Guava Iterable.filter() 的方法可以进一步减少代码。 .

MyAdapterInterface 需要是适配器的接口(interface)或共享父类,共享此过滤器需要调用的所有适配器方法。

    public class MyFilter<A extends MyAdapterInterface,T> extends Filter {
        private final A adapter;
        private final Predicate<T> comparator; // Java 8 class - can easily be created by hand if you are using pre Java 8
        // see https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html

        private final List<T> originalList;
        private final List<T> filteredList;

        private MyFilter(A adapter, List<T> originalList, Predicate<T> predicate) {
            super();
            this.adapter = adapter;
            this.comparator = comparator;
            this.originalList = new LinkedList<>(originalList);
            this.filteredList = new ArrayList<>();
        }

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            filteredList.clear();
            final FilterResults results = new FilterResults();

            if (constraint.length() == 0) {
                filteredList.addAll(originalList);
            } else {
                final String filterPattern = constraint.toString().toLowerCase().trim();

                for (final T animal : originalList) {
                    if (predicate.test(animal)) {
                        filteredList.add(animal);
                    }
                }
            }
            results.values = filteredList;
            results.count = filteredList.size();
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            adapter.clearResults();   // method to be added to MyAdapterInterface
            adapter.addResults(results.values);  // method to be added to MyAdapterInterface
            adapter.notifyDataSetChanged();
        }
    }

关于java - 如何创建一个适用于两个不同对象的基类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39945181/

相关文章:

java - 如何使用在主类中调用/设置的另一个类在类上设置值

java - 在 MacOS 上安装 R 并从源代码编译包 - 使事情正常运行的组件和步骤

java - 使用 Libgdx 进行高效 3D block 渲染

java - 如何从 SQLiteOpenHelper 访问 StartActivityForResult()?

Java Swing : Resizing component in JFrame without affecting other components

java - maven - 创建生成的 jar 文件的存档

java - 我无法在 Mysql 数据库中存储 .doc 简历

java - ScrollView 不随图表一起滚动

java - 我怎样才能让maven在 "mvn test"处运行mySQL插件

java - 如何为区域设置名称创建本地化字符串?