Only permits children classes as generic parameters

52 Views Asked by At

Java 17

I'm implementing the following method:

public static <T, O extends T, V> Optional<V> toOption(T t, Function<? super O, ? extends Optional<V>> f, Class<O> cls){
    Optional<O> opt;
    if(cls.isAssignableFrom(t.getClass())){
        opt = some((O) t);
    } else
        opt = empty();
    return opt.flatMap(f);
}

which is supposed to return non empty Optional if the runtime type of argument of type T is subclass of type parameter O and flatMap it with the given Function. The problem with this implementation is that the following still compiles:

toOption(123, v -> Optional.of(v), String.class);

But Integer and String are unrelated. So O extends T does not really works. Is there a way to make such cases not compile?

1

There are 1 best solutions below

0
Emanuel Trandafir On

To simplify the question, I believe you cannot enforce a complication error for a function like this, if the arguments do not match the generic rule:

public <A, B extends A> void doNothing(A a, Class<B> b) {
}

@Test
void test() {   
    doNothing(123, String.class);
}

However, you can simplify the code a bit and you can throw runtime exceptions if the types do not match. Though, since you are going with Optionals, you can simply stick to Optional.empty, as you had in your example. A simple refactor:

public static <T, O extends T, V> Optional<V> toOption(
        T t, Function<? super O, ? extends Optional<V>> f, Class<O> cls) {

    return assign(t, cls)
            .flatMap(x -> some(x))
            .flatMap(f);
}

private static <T, O> Optional<O> assign(T t, Class<O> cls) {
    if (cls.isAssignableFrom(t.getClass())) {
        return Optional.ofNullable((O) t);
    } 
    return Optional.empty();
}