Java дженерики возвращают дженерики c в качестве более точных c двух типов? - PullRequest
0 голосов
/ 15 апреля 2020

В настоящее время у меня есть проект, в котором я фильтрую некоторые сущности, используя набор классов, реализующих обобщенный класс c Filter<T extends Entity>, где T - наиболее конкретная c сущность, с которой будет работать фильтр c. , Немного многословно постоянно создавать новые экземпляры, поэтому я также создал Builder. Все было замечательно, кроме тех случаев, когда я пытаюсь добавить AndFilter в конструктор.

Вот как выглядит мой AndFilter

public class AndFilter<T extends Entity> implements Filter<T>{
    private Filter<? super T> a;
    private Filter<? super T> b;

    public AndFilter(Filter<? super T> a, Filter<? super T> b){
        this.a = a;
        this.b = b;
    }

    @Override
    public boolean shouldInclude(T entity) {
        return a.shouldInclude(entity) && b.shouldInclude(entity);
    }
}

, а вот функция построения, которую я пытался приступить к работе (мой конструктор - просто функции по умолчанию в интерфейсе фильтра)

public interface Filter<T extends Entity> {
    boolean shouldInclude(T entity);

    default AndFilter and(Filter<? extends Entity> other){
        return new AndFilter<>(this, other);
    }

    default Filter<T> not(){
        return new NotFilter<>(this);
    }
}

Мне нужно иметь возможность параметризировать возвращение and (), но все мои попытки провалились. Теоретически, AndFilter должен быть параметризован для того или иного типа, в зависимости от того, что конкретнее c, но я не знаю, как я могу это сделать, и я начинаю думать, что это просто невозможно. Если это не так, любые предложения по альтернативным способам, которыми я мог бы реализовать подобное поведение (не вызывая новый AndFilter <> (x, y) для И сравнивайте два фильтра), были бы оценены.

Редактировать: у меня есть различные классы все наследуют от сущности со своими собственными частными свойствами * Таким образом, у меня есть фильтр реализует DistanceFilter (поскольку все объекты имеют положение и, следовательно, расстояние), но у меня также есть фильтр реализует AggressionFilter, поскольку только у хищников есть свойство агрессии. Проверка того, удовлетворяет ли хищник обоим фильтрам, должна быть возможной, поскольку хищник обладает всеми необходимыми свойствами, и он работает. Я могу вызвать новый AndFilter <> (new DistanceFilter (), новый AggressionFilter ()), и он работает нормально, но когда я пытаюсь поместить эту инициализацию в функцию, я не могу заставить работать возвращаемый тип

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

Я наконец-то понял, как решить мою собственную проблему

default <F extends T> AndFilter<F> and(Filter<? super F> other){
    return new AndFilter<>(this, other);
}

Должен дать функции свой собственный тип c (F), который по крайней мере является типом текущего фильтра, а затем другой фильтр должен быть максимально такого типа. Возвращенный AndFilter является параметризованным для этого типа.

0 голосов
/ 15 апреля 2020

AndFilter имеет параметризованный тип, AndFilter должен быть связан с T. AndFilter должен состоять из объектов Filter с тем же типом, которым он связан, T, который расширяет Entity.

default AndFilter<T> and(Filter<? extends Entity> other){
    return new AndFilter<>(this, other);
}
public class AndFilter<T extends Entity> implements Filter<T>{

    private Filter<T> a;

    private Filter<T> b;

    public AndFilter(Filter<T> a, Filter<T> b){
        this.a = a;
        this.b = b;
    }
}

Пример реализации с классом MyEntity, который расширяет сущность и имеет единственный член класса name типа String.

        MyEntity foo = new MyEntity("Foo");

        MyEntity bar = new MyEntity("Bar");

        MyEntity fooBar = new MyEntity("FooBar");

        Filter<MyEntity> fooFilter = e -> e.name.contains("Foo");

        Filter<MyEntity> barFilter = e -> e.name.contains("Bar");

        Filter<MyEntity> fooBarFilter = fooFilter.and(barFilter);

        System.out.println(String.format("Foo: %s", fooFilter.shouldInclude(foo)));
        System.out.println(String.format("Bar: %s", barFilter.shouldInclude(bar)));
        System.out.println(String.format("FooBar: %s", fooBarFilter.shouldInclude(fooBar)));
...