为什么我们不能在功能接口中重载抽象方法? (Java)

时间:2019-02-28 01:13:11

标签: java oop overloading functional-interface

因此,我熟悉Java中的功能接口以及它们与lambda表达式的结合使用。一个功能接口只能包含一个抽象方法。在lambda表达式中使用此孤独方法时,无需指定其名称-由于接口中只有一个抽象方法,因此编译器知道您正在引用的方法。

示例:

// Functional Interface:

@FunctionalInterface
public interface Ball
{
    void hit();
}

// Lambda to define, then run the hit method:

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

b.hit();

尽管显而易见的是,为什么一个功能接口只能包含一个抽象方法,但我不明白为什么无法重载该方法。

例如,以下内容将不会编译:

// (NOT) Functional Interface:

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

// Lambda to define, then run the hit method:

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

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

编译器指出Ball接口不起作用,因为它包含多个方法,但是在这种情况下,我不明白为什么会出现问题-只要这两个方法采用不同的参数,应该可以根据定义的参数推断出我在lambda中引用的方法。

有人可以解释为什么无法在功能接口内重载抽象方法吗?

2 个答案:

答案 0 :(得分:4)

在没有方法重载的语言中,方法由该类中它们的名称唯一标识(暂时忽略重写)。

在Java中,情况有所不同。引用oracle docs

  

重载方法

     

Java编程语言支持重载方法,并且Java可以区分具有不同方法签名的方法。这意味着,如果类中的方法具有不同的参数列表,则它们可以具有相同的名称(对此有一些限定条件,将在标题为“接口与继承”的课程中进行讨论)。

因此,我们知道方法也可以通过其签名来识别。如果两个方法共享一个名称但没有相同的签名,则它们是不同的方法。不要让他们的共享名欺骗您,以为他们之间有某种联系。

考虑到这一事实,我们可以轻松地创建一个示例,其中如果方法按照您描述的方式进行操作,则会发生未定义的行为:

Ball ba = (boolean miss) -> System.out.println(miss);
someFunction(ba)
public void someFunction(Ball ball) {
    ball.hit();
}

在这种情况下,您会期望什么行为?它是未定义的!


但是,您可以使用default methods。我不太了解您的情况,无法判断这是否合适,但是您可以这样做:

@FunctionalInterface
public interface Ball
{
    default void hit() {
        hit(true);
    }

    void hit(boolean miss);
}

documentation for FunctionalInterface中解释了为什么这样做:

  

从概念上讲,功能接口只有一种抽象方法。由于默认方法具有实现方式,因此它们不是抽象的

答案 1 :(得分:0)

只要您声明实现Ball接口的类,就必须实现所有抽象方法。 例如,如果您这样做:

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

然后您将b作为参数传递,并且其他代码调用b.hit(true)将会崩溃,因为未实现hit(boolean miss)

因此,功能接口只能具有一个抽象方法。