有没有办法在功能接口中重载抽象方法?

时间:2019-05-30 17:16:38

标签: java java-8 overloading functional-interface

我希望能够提供一个接受几种不同类型的lambda函数的功能接口。

我读了this。该问题的第一个答案阐明了为什么在功能接口中重载抽象方法会导致未定义行为。但是,如果我提供所有默认值,是否有办法等同于重载功能接口中的抽象方法?

我希望能够编写如下代码:

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);

所需的结果将是:

You hit it!
default false
default hit
false

考虑以下(不可编译的)代码(主要是从链接的问题中复制):

@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);
    }

}

我正在寻找可以编译的替代代码。

4 个答案:

答案 0 :(得分:1)

您可以执行以下操作。但是,您需要正确命名变量,以跟踪arg和使用它的consumer

@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();
   }
}

答案 1 :(得分:0)

关于功能接口的第一件事是,它只能有一个抽象方法。在这种情况下,您甚至不能想到第二种方法(也可以是抽象方法)。您可以使用任意数量的默认方法。

因此不可能100%给出答案,并且上面的代码将保留编译错误,因为您保留@FunctionalInterface批注,该批注严格禁止保留多个抽象方法。 根据您的代码

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

    public abstract void fly(int a);

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

第1行和第2行会抛出编译时错误,因为java通过方法名看到它们是相同的,并且参数类型是相同的,它们永远不会打扰返回类型或默认值等。(重载的主要规则)。

如果删除第1行和第2行,那么代码也会引发错误,因为@functionalinterface将给出编译错误,指出 无效的'@FunctionalInterface'注释; MyInter不是功能界面

希望这能回答您的问题...

答案 2 :(得分:0)

您可以将接口包装在一个类中,然后在内部将方法调用传递给接口。

示例代码:

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);
    }

    static public 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);
    }
}

程序输出:

You hit it!
default false
default hit
false

答案 3 :(得分:-2)

一种可行的解决方案是拥有一个名为DefaultBall的类(如有必要,可以使用抽象类),该类实现接口Ball并使用默认实现覆盖该方法。

示例代码:

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

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

    static public class DefaultBall implements Ball{    
        public final void hit(boolean b){
            System.out.println("default hit");
        }
    }

    public interface Ball{
        void hit(boolean miss);
    }
}

如有需要,请随时进行澄清。