1

I would like to be able to provide a functional interface that accepts several different types of lambda functions.

I read this. The first answer to this question clarifies why overloading an abstract method in a functional interface could cause undefined behavior. However, is there a way to do the equivalent of overloading an abstract method in a functional interface if I supply all of the defaults?

I would like to be able to write something like the following code:

Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss);

b.hit();
b.hit(false);
ba.hit();
ba.hit(false);

The desired result would be:

You hit it!
default false
default hit
false

Consider the following (non-compilable) code (mostly copied from the linked question):

@FunctionalInterface
public interface Ball
{
    void hit();
    void hit(boolean miss);
    default void hit(){
        System.out.println("default hit");
    }
    default void hit(boolean miss){
        System.out.println("default" + miss);
    }

}

I am looking for an alternative to this code that would compile.

  • 3
    A functional interface allows only one abstract method. How are you expecting this to work? – ernest_k May 30 '19 at 17:32
  • Note that you cannot have two definitions of a method in an interface, even if one is abstract and the other is default. Have you tried compiling your code? I do not think that it will compile. @Yehuda – Kartik Soneji May 30 '19 at 17:33
  • 1
    @KartikSoneji As was written in the question, the code is non-compilable. I am looking for a way to create something equivalent. – Yehuda Rimon May 30 '19 at 17:35
  • 1
    https://stackoverflow.com/q/25299653/2711488 • https://stackoverflow.com/q/21833537/2711488 (note the answers beneath the accepted one) – Holger May 31 '19 at 10:26

3 Answers3

2

You could do something like this. But you would need to name your variables properly to keep track of both the arg and the consumer that takes it.

@FunctionalInterface
interface Ball<T> {
   void hit();

   static <T> Ball<T> withArg(T arg, Consumer<T> com) {
      return () -> com.accept(arg);
   }
}

public class Demo {
   public static void main(String[] args) {
      Ball<Boolean> b = () -> System.out.println("You Hit it!");
      b.hit();
      Ball<Boolean> ba = Ball.withArg(false, a -> System.out.println(a));
      Ball<Boolean> bb = Ball.withArg(true, a -> System.out.println(a));
      ba.hit();
      bb.hit();
   }
}
Naman
  • 27,789
  • 26
  • 218
  • 353
WJS
  • 36,363
  • 4
  • 24
  • 39
1

You could wrap the interface in a class and then pass on the method calls to the interfaces internally.

Example code:

public class Test{
    public static void main(String... args) throws Exception{
        Ball b = new Ball(() -> System.out.println("You hit it!"));
        Ball ba = new Ball((boolean miss) -> System.out.println(miss));

        b.hit();
        b.hit(false);
        ba.hit();
        ba.hit(false);
    }

    public static class Ball{
        final Hit a;
        final HitBoolean b;
        
        public Ball(Hit a){
            this.a = a;
            b = (miss) -> System.out.println("default " + miss);
        }
        
        public Ball(HitBoolean b){
            this.b = b;
            a = () -> System.out.println("default hit");
        }
        
        public void hit(){
            a.hit();
        }
        
        public void hit(boolean miss){
            b.hit(miss);
        }
    }

    public interface Hit{
        void hit();
    }
    
    public interface HitBoolean{
        void hit(boolean miss);
    }
}

Output of the program:

You hit it!
default false
default hit
false
Kartik Soneji
  • 1,066
  • 1
  • 13
  • 25
0

first thing about functional interface is , it can have only one abstract method.In that case you cant even think of the second method (let it be abstract method too). you can have any number of default methods.

So answer is 100% not possible and Your code above will get compilation error as you kept @FunctionalInterface annotation which strictly prohibits keeping more than one abstract method. As per your code

@FunctionalInterface
public interface MyInter {
    public abstract void fly();

    public abstract void fly(int a);

    default void fly() {}          \\line1
    default void fly(int g) {   }   \\line2
}

line 1 and 2 will throw compile time error as java sees them by method name are same and argument types are same , they will never bother of return type or default or etc..(primary rule of overloading).

more over if remove line 1 and 2 , then too code will throw error because @functionalinterface will give compilation error stating invalid '@FunctionalInterface' annotation; MyInter is not a functional interface .

Hope this answers your question...

Kathiresan. N
  • 48
  • 1
  • 12