0

I'm trying to pass a subclass as a parameter to a method. So far I've not been successfull, and even told it's not possible to do in Java. I want the opinion of stackoverflow, and suggestions to make it work.

Let's assume 'HelloEvent' extends 'Event'...

I have a method :

public void addListener(Consumer<? extends Event> consumer) { 
     [...]
}

and another method :

public void listen(HelloEvent helloEvent) { 
    [...]
}

I want to do this :

addListener(this::listen);

In IDEA I have the error 'Cannot resolve method listen'. Of course this happens because 'listen' is not exactly an Event, but rather a subclass.

Is there a way to do this? Maybe a work around?

I've tried having it being a Function or replacing 'extends' with 'super' and it does not work. I've been attempting to fix this problem for a few weeks now.

RealmSpy
  • 345
  • 1
  • 4
  • 12
  • Where are you calling `addListener(this::listen);`? – Jacob G. Jun 12 '18 at 23:52
  • Anywhere really, in this case we could say addListener and listen are both in the same class and we call addListener in the main method. – RealmSpy Jun 12 '18 at 23:59
  • But your main method is `static`, no? You won't be able to use `this`. – Jacob G. Jun 13 '18 at 00:15
  • You're right forget that... Not a static method. – RealmSpy Jun 13 '18 at 00:24
  • I actually get a different error, having to do with incompatible types ([see example](https://ideone.com/VjcdPu)), although there's a way to fix it. IDEA gives me this same error too, so your actual code has a problem which you haven't described here. In any case, though, what the answers are saying is probably right: you shouldn't be using `Consumer extends Event>` for this in the first place. – Radiodef Jun 13 '18 at 00:29

2 Answers2

1

Well, you can't just listen to any Event, only to HelloEvents.

It should probably be Consumer<? super Event>, because e.g. What is PECS (Producer Extends Consumer Super)? .

In that case, you could write

addListener(event -> {
  if (event instanceof HelloEvent) {
    listen((HelloEvent) event);
  }
});

...but nothing short of that will work, honestly. You have to check that it's a HelloEvent explicitly.

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
0

Even if you could do this, you would get a ClassCastException when the listener is called. However, if you included the type with addListener, you could add logic to filter that.

void addListener(Consumer<? super Event> listener) {
    [...]
}
<T extends Event> void addListener(Class<T> type, Consumer<T> listener) {
    addListener(evnt -> {
        if (type.isInstance(evnt))
            listener.accept(evnt);
    });
}
killjoy
  • 3,665
  • 1
  • 19
  • 16