Как определить BiFunction с использованием поставщика в качестве запасного варианта для создания некоторых объектов? - PullRequest
0 голосов
/ 29 марта 2019

Что не так с этим кодом?Мне нужно создать фабричный метод, который зависит от BiFunction для выполнения своей работы.

Компилятор сказал мне:

The method apply(Class<T>, Supplier<I>) 
in the type BiFunction<Class<T>,Supplier<I>,T> 
is not applicable for the arguments (Class<A>, B::new)

, но B расширяет A, B :: new производит поставщикадля B ...

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.function.BiFunction;
import java.util.function.Supplier;

import org.junit.jupiter.api.Test;

public class BiFunctionTest {

    static interface A {

    }

    static class B implements A {

    }

    static interface C {

    }

    static class D implements C {

    }

    private A a;
    private C c;

    public static <T, I extends T> BiFunctionTest create(
            BiFunction<Class<T>, Supplier<I>, T> fn) {
        BiFunctionTest o = new BiFunctionTest();
        o.a = fn.apply(A.class, B::new);
        o.c = fn.apply(C.class, D::new);
        return o;
    }

    @Test
    public void testBiFunction() {
        BiFunctionTest o = BiFunctionTest.create((i, s) -> s.get());
        assertEquals(B.class, o.a.getClass());
        assertEquals(D.class, o.c.getClass());
    }

}

Ответы [ 3 ]

0 голосов
/ 29 марта 2019
 public static <T> BiFunctionTest create2(
        BiFunction<Class<T>, Supplier<T>, T> fn) {
    BiFunctionTest o = new BiFunctionTest();
    Supplier<A> u = B::new;
    o.a = fn.apply(A.class, u);
    Supplier<? extends C> u2 = D::new;
    o.c = fn.apply(C.class, u2);
    return o;
}

@Test
public void testBiFunction() {
    BiFunctionTest o = BiFunctionTest.create2((i, s) -> s.get());
    assertEquals(B.class, o.a.getClass());
    assertEquals(D.class, o.c.getClass());
}

производит

The method apply(Class<T>, Supplier<T>) 
in the type BiFunction<Class<T>,Supplier<T>,T> 
is not applicable for the arguments (Class<BiFunctionTest.A>, Supplier<BiFunctionTest.A>)

и

The method apply(Class<T>, Supplier<T>) 
in the type BiFunction<Class<T>,Supplier<T>,T> 
is not applicable for the arguments (Class<BiFunctionTest.C>, Supplier<capture#1-of ? extends BiFunctionTest.C>)
0 голосов
/ 30 марта 2019

решил это, добавив дополнительный интерфейс, но требует приведения ..: /


import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.function.BiFunction;
import java.util.function.Supplier;

import org.junit.jupiter.api.Test;

public class BiFunctionTest {

    static interface A {
    }

    static interface B extends A {
    }

    static class ObjectB implements B {
    }

    static interface C extends A {
    }

    static class ObjectC implements C {
    }

    private B b;
    private C c;

    public static BiFunctionTest create3(
            BiFunction<Class<? extends A>, Supplier<? extends A>, A> fn) {
        BiFunctionTest o = new BiFunctionTest();
        o.b = (B) fn.apply(B.class, ObjectB::new);
        o.c = (C) fn.apply(C.class, ObjectC::new);
        return o;
    }

    @Test
    public void testBiFunction() {
        BiFunctionTest o = BiFunctionTest.create3((i, s) -> s.get());
        assertEquals(ObjectB.class, o.b.getClass());
        assertEquals(ObjectC.class, o.c.getClass());
    }

}
0 голосов
/ 29 марта 2019

Обобщения должны точно совпадать, они не проверяются ковариантно / контравариантно, если они явно не объявлены как таковые. Так что Supplier<B> это не Supplier<A>, а Supplier<? extends A>.

Ваша подпись изменится на следующее:

 public static <T, I extends T> BiFunctionTest create(BiFunction<Class<? extends T>, Supplier<? extends I>, T> fn) {...

Но теперь для второй проблемы тело вашей функции не является универсальным с точки зрения T, так как вы используете A.class и B::new. Здесь следует использовать общую сигнатуру, если реализация на самом деле не зависит от этих типов A и B, но это не так.

Итак, сбросив дженерики из подписи:

public static BiFunctionTest create(BiFunction<Class<? extends A>, Supplier<? extends A>, A> fn) {...

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

    BiFunctionTest o = new BiFunctionTest();
    o.a = fn.apply(A.class, B::new);
    return o;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...