4

Consider functional interfaces A and B extends A. Is it possible to create an instance implementing not only A but also B with a lambda expression when only A is required?

Example:

interface A {
    void foo();
}

interface B extends A {}

void bar(A arg) {
    System.out.println(arg instanceof B);
}

/* somewhere in a block */
    bar( () -> {} ); // Prints "false"

How could I call bar(A) so that it prints true?

I would find this useful in event listeners, where subinterfaces could specify additional data about the listener, e.g. if a Listener also implements ConcurrentListener, it is invoked concurrently.

OLEGSHA
  • 388
  • 3
  • 13

2 Answers2

8

Simply do a cast to tell the compiler the type you want:

A a = (B)() -> someAction();
System.out.println(a instanceof B); // true

I would find this useful in event listeners, where subinterfaces could specify additional data about the listener, e.g. if a Listener also implements ConcurrentListener, it is invoked concurrently.

That sounds like bad design (though I can't explain why...). Maybe you could have a isConcurrent method in the interface that implementers need to implement?

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 1
    Nice! For those like me who were wondering how a lambda can be automagically cast to an interface [see here](https://stackoverflow.com/q/28509596/314291). – StuartLC Jun 04 '18 at 14:01
  • Thanks for the reply! As for your workaround using new methods, that is exactly what I would have done if I wasn't trying to make listeners `@FunctionalInterface`s. – OLEGSHA Jun 04 '18 at 17:50
2

You can explicitly cast lambda expression to B:

bar((B)() -> {});

or assign lambda expression to a variable:

B lambda = () -> {};
bar(lambda);
frenchu
  • 288
  • 3
  • 9