3

I have a functional interface defined as

@FunctionalInterface
public interface SetupConstraint<T extends GraphicalObject> {
    public void setup(T object);
}

The class hierarchy here is

OutlineRect is a subclass of GraphicalObject
SelectableOutlineRect is a subclass of OutlineRect that implements Selectable

Now I have

SelectableOutlineRect r = new SelectableOutlineRect();
SetupConstraint<? extends OutlineRect> constraint = ...; // from somewhere else
constraint.setup(r);

In the final line of code, the compiler gives the following error:

The method setup(capture#1-of ? extends OutlineRect) in the type
SetupConstraint<capture#1-of ? extends OutlineRect> is not
applicable for the arguments (SelectableOutlineRect)Java(67108979)

I'm so confused about this right now... I'm fairly new to this but I believe since SelectableOutlineRect is a subclass of OutlineRect this should not report an error. What am I missing here?

Niwatori
  • 31
  • 1
  • 4
  • In my experience, `?` wildcards only work in method declarations. – Powerlord Mar 24 '20 at 06:09
  • Your `SetupConstraint` interface is a consumer, so at _use sites_ you should have `? super ...` instead of `? extends ...`. Related: [What is PECS (Producer Extends Consumer Super)?](https://stackoverflow.com/q/2723397/6395627). – Slaw Mar 24 '20 at 06:20
  • @Powerlord They can also be used in the parameterized type of a field/variable. – Slaw Mar 24 '20 at 06:23
  • @Slaw Oh wow thank you for the link. It works when I changed the code to SetupConstraint super SelectableOutlineRect>. But may I ask how should I interpret SetupConstraint being a consumer? It's kinda different from Collection or others which are easier to understand. – Niwatori Mar 24 '20 at 06:47
  • [Here](https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html) and [here](https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html) are two links that explain the stuff pretty well. Keep in mind, that ```?``` creates a *dynamic* type for you at runtime. – akuzminykh Mar 24 '20 at 06:50
  • Your interface is a consumer because the type variable (`T`) is only used as a parameter type. The method(s) _consume_ arguments of type `T`. The interface would be a producer if the type variable was only used as a return type. In this case, the method(s) _produce_ results of type `T`. Neither case precludes the existence of interfaces that have some consumer methods _and_ some producer methods, or even some methods that are both. – Slaw Mar 24 '20 at 06:53

0 Answers0