为什么Java 8不允许使用非公共默认方法?

Why does Java 8 not allow non-public default methods?

让我们举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface Testerface {

    default public String example() {
        return"Hello";
    }

}

public class Tester implements Testerface {

    @Override
    public String example() {
        return Testerface.super.example() +" world!";
    }


}

public class Internet {

    public static void main(String[] args) {
        System.out.println(new Tester().example());
    }

}

简单地说,这将打印Hello world!。但是假设我正在使用Testerface#example的返回值执行其他操作,例如初始化数据文件并返回不应离开实现类的敏感内部值。为什么Java不允许在默认接口方法上使用访问修饰符?为什么它们不能被保护/私有,并且可能被子类提升(类似于扩展父类的类如何为重写方法使用更可见的修饰符)?

一个常见的解决方案是移动到一个抽象类,但是在我的特定情况下,我有一个枚举接口,所以这里不适用。我认为它要么被忽视了,要么是因为接口背后的原始想法,即它们是可用方法的"契约",但我想我需要输入有关这方面的内容。

我读过"为什么是"Java 8接口方法中不允许的?,这说明:

The basic idea of a default method is: it is an interface method with a default implementation, and a derived class can provide a more specific implementation

在我看来,能见度不会破坏这一点。

与关联问题一样,由于它看起来很难被解决,在这个问题上权威性的回答会得到赞赏,而不是基于观点的回答。


正如我们所看到的,为什么在Java 8接口方法中不允许"同步"的原因?为什么Java语言8接口方法中不允许使用"最终"?扩展接口来定义行为比它最初可能出现的要微妙得多。事实证明,每个可能的修饰符都有自己的故事;这不仅仅是盲目复制类的工作原理。(这在事后看来至少是显而易见的,因为用于单继承的OO建模工具不会自动用于多继承。)

让我们从一个明显的答案开始:接口一直被限制为只具有公共成员,而在Java 8中,我们将默认方法和静态方法添加到接口中,但这并不意味着我们必须改变所有的东西,仅仅是为了"更像"类。

与EDCOX1、0和EDCOX1(1)不同,这将是支持默认方法的严重错误,较弱的可访问性,尤其是私有性,是合理的特征。私有接口方法,无论是静态的还是实例的(请注意,这些方法不会是默认的,因为它们不参与继承),都是一个非常明智的工具(尽管它们很容易被非公共助手类模拟)。

我们实际上考虑了在Java 8中执行私有接口方法;这主要是由于资源和时间限制而从列表底部掉下来的东西。这项功能很可能会在某一天重新出现在待办事项列表中。

然而,打包和保护方法比它们看起来更复杂;多重继承的复杂性和protected真正意义的复杂性将以各种不那么有趣的方式相互作用。所以我不会因此而屏住呼吸。

所以,简短的答案是,私有接口方法是我们在8年就可以做到的,但是我们不能做所有可以做的事情,而且仍然可以发布,所以它被切断了,但可以恢复。