beatbrot
beatbrot

Reputation: 175

How can I use the most specialized type of two objects as return type?

What I basically want is, that the more specialized type is inferred like in the following example:

Predicate<Object> first;
Predicate<String> second;

Predicate<String> firstOr = first.or(second);
Predicate<String> secondOr = second.or(first);

How would the method signature of or(...) look like to accomplish this?

Upvotes: 3

Views: 92

Answers (2)

Misha
Misha

Reputation: 28183

This can be accomplished with the following declaration of Predicate<T>::or:

default <R extends T> Predicate<R> or(Predicate<? super R> other) {
    return r -> this.test(r) || other.test(r);
}

This would allow or to create a Predicate for any subtype of both Predicate types. So, for example, the following would work:

Predicate<Object> first;
Predicate<Number> second;

Predicate<Integer> firstOr = first.or(second);
Predicate<Integer> secondOr = second.or(first);

Upvotes: 4

marstran
marstran

Reputation: 28066

I think you need two overloads for this to work. However, because the only difference between the overloads is in the type parameters, they would clash because of erasure. You therefore need to name them differently (which would not make them actual overloads anymore).

This could be the signatures:

/* In this case, the input Predicate has the most specific type.
 * Use this in the first.or(second) case
 */
public <R extends T> Predicate<R> or1(Predicate<R> pred);

/* In this case, the receiver Predicate has the most specific type.
 * Use this in the second.or(first) case
 */
public Predicate<T> or2(Predicate<? super T> pred);

Both methods would work the same if the type parameters are equal (for example if both first and second had the type Predicate<String>)

Upvotes: 2

Related Questions