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

8 浏览
0 Comments

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

让我们举个例子:\n

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

\n简单来说,这将打印出Hello world!。但是假设我正在对Testerface#example的返回值进行其他操作,例如初始化数据文件并返回不应该离开实现类的敏感内部值。为什么Java不允许在默认接口方法上使用访问修饰符?为什么它们不能是protected/private,并且可以由子类提升(类似于扩展父类的类可以为重写方法使用更可见的修饰符)?\n常见的解决方法是转换为抽象类,但在我特定的情况下,我有一个用于枚举的接口,所以这不适用于这里。我想这可能是因为最初接口的设计理念是它们是可用方法的“合同”,或者可能是因为这个问题被忽视了,但我想知道其中的原因。\n我已经阅读了“Why is “final” not allowed in Java 8 interface methods?”,其中提到:\n

\n默认方法的基本思想是:它是一个具有默认实现的接口方法,派生类可以提供更具体的实现\n

\n对我来说,这听起来好像可见性并不会破坏这个方面。\n与链接问题一样,因为它似乎很难被关闭,在这个问题上,我希望得到一个权威的答案,而不是基于观点的答案。

0
0 Comments

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

在我们在“为什么Java 8接口方法不允许synchronized?”和“为什么Java 8接口方法不允许final?”中看到的内容中,扩展接口来定义行为比起初看起来更加微妙。事实证明,每个可能的修饰符都有自己的故事;这不仅仅是盲目地从类的工作方式中复制。这至少在事后是明显的,因为对于单继承的面向对象建模工具并不能自动适应多继承。

让我们从显而易见的答案开始:接口一直被限制为只有公共成员,虽然我们在Java 8中为接口添加了默认方法和静态方法,但这并不意味着我们必须改变一切,只是为了“更像”类。

与支持默认方法的不同,支持更弱的访问权限,尤其是私有访问权限,是一个合理的功能考虑。私有接口方法,无论是静态的还是实例的(请注意,这些不是默认方法,因为它们不参与继承),是一个完全合理的工具(虽然可以通过非公共辅助类来轻松模拟)。

实际上,在Java 8中我们确实考虑过实现私有接口方法;这主要是由于资源和时间限制而被搁置的事情。这个功能有可能在某一天重新出现在待办事项列表上。(更新:Java 9中添加了接口中的私有方法。)

然而,包和受保护的方法比看起来更加复杂;多继承的复杂性和的真正含义的复杂性将以各种不太有趣的方式互动。所以我不会期望这个功能很快就会出现。

所以,简短的答案是,私有接口方法是我们在8中本可以做的事情,但我们不能做所有可能做的事情并且仍然发布,所以它被取消了,但有可能会回来。

缺乏接口上的私有方法是否与默认方法鼓励开发人员暴露修改器?

我认为“鼓励”是一个错误的词。它没有起到阻碍的作用。我们本来希望在8中将私有方法添加到接口中,但在你所拥有的时间和资源中能做的事情是有限的。

好消息是,Java 9中似乎将支持接口中的私有方法。

嗯,尽管Java 8/9中的所有这些新功能似乎非常有用和方便,但我觉得它变得有点混乱了。对于我对“接口”的理解,它的定义更接近于“契约”而不是它已经变成的样子。我认为向语言中添加一个代表“没有状态的类”的新实体,而不是扩展“接口”实体,将会更加美观。我想到的是类似“mixin”的东西。

毋庸置疑,在做出这个决定之前进行了广泛的讨论。结论是,创建一个几乎与接口相同但并非完全相同的新的顶级抽象(mixin、trait等),会更加混乱和侵入性 - 并且可能也无法满足人们对mixin/trait的预期期望。(很容易说“这是不完美的,你应该做些其他的事情”,但我们还必须更深入地思考一下,其他的替代方案本身是否更糟糕。)

这实际上是一个非常好的观点。我自己开始使用默认方法,直到某个时刻我发现了你所做的确切观察。我完全同意。

0