Обобщения в рекурсивном методе - PullRequest
0 голосов
/ 23 сентября 2018

Я уже несколько часов бьюсь головой об это стол.

У меня есть эта карта:
private static Map<Class<? extends BaseClass>, Predicate<? extends BaseClass>> constraints;

И у меня есть этот метод:

public static <C extends BaseClass> Predicate<C> getConstraints(Class<? super C> clazz) {
    if (clazz == BaseClass.class) {
        return (Predicate<C>) constraints.getOrDefault(BaseClass.class, x -> true);
    }
    Class<? super C> superClass = clazz.getSuperclass();
    return constraints.getOrDefault(clazz, x -> true).and(getConstraints(superClass));
}

Все, что предполагается сделать, - это связать все ограничения для определенного класса (и суперклассов) в Predicate<T>, используя метод and().Обобщения кажутся мне логичными, но я все равно получаю сообщение об ошибке при выполнении рекурсивного вызова.getConstraints(Class<? super C>) cannot be applied to Class<capture of ? super E>.Я не понимаю, потому что superClass относится к типу Class<? super C>, который является именно тем параметром, который принимает мой метод.Есть идеи?

1 Ответ

0 голосов
/ 23 сентября 2018

Вы можете использовать переменную типа, которая представляет суперкласс:

@SuppressWarnings("unchecked")
public static <S extends BaseClass, C extends S> Predicate<C> getConstraints(Class<C> clazz) {
    if (clazz == BaseClass.class) {
        return (Predicate<C>) constraints.getOrDefault(BaseClass.class, x -> true);
    }
    Class<S> superClass = (Class<S>) clazz.getSuperclass();
    Predicate<C> p1 = (Predicate<C>) constraints.getOrDefault(clazz, x -> true);
    Predicate<S> p2 = getConstraints(superClass);
    return p1.and(p2);
}

Вам также нужно будет привести результат getOrDefault, так как помещение Predicate в карту «забывает» типинформацию, и вы получите общий Predicate<? extends BaseClass>, который вы не можете использовать напрямую.

...