学家Bloch在为Java 6
撰写的Effective Java中提到了以下内容(第17项):
如果你觉得你必须允许继承这样一个类,那么 合理的方法是确保该类永远不会调用任何一个 它的可覆盖方法并记录了这一事实。换一种说法, 彻底消除了班级对可覆盖方法的自我使用。
第18项:
如果使用抽象类来定义类型,则可以离开程序员 谁想要添加功能,别无选择,只能使用 遗产。由此产生的类不那么强大,也更脆弱 比包装类。
虽然不允许接口包含方法实现, 使用接口来定义类型并不妨碍您提供 对程序员的实施帮助。
现在在Java 8
中使用其默认方法的实现(使用接口中的其他方法)接口对于继承是危险的。
例如:
public inteface MyInterface{
public void compute(Object o);
public default void computeAll(List<Object> oo){
for(Object o: oo)
compute(o); //self-use
}
}
因此,根据J. Bloch的说法,当我们尝试实现接口时,它可能会引入一些问题,因为:
覆盖这样的方法(类似于J.Bloch提供的):
public class MyInterfaceCounter implements MyInterface{
private int count = 0;
@Override
public void compute(Object o) {
count++;
}
@Override
public void computeAll(List<Object> oo){
count += oo.size(); //Damn!!
MyInterface.super.computeAll(oo);
}
}
客户端访问接口的内部,即他们必须知道默认实现。
在Java 8中如何处理它? Effective Java的规则是否仍然适用?
此外,我们不能将默认方法声明为final
(正如我们可以为类做的那样,它会使自用对于重写器来说不太危险)。
答案 0 :(得分:3)
好的,请从your previous question获取答案,看看我们在这里可以应用的内容:
你可以简单地避免自我使用。
在这种情况下你不能。实现该接口时,您唯一依赖的选择(如果您想提供默认实现)是方法compute
。你必须使用或不使用它。
你可以让其中一个方法参与最终,因此无法覆盖。
这也不适用于界面。
你可以让班级成为最终版,因此无法扩展。
这在界面中不起作用。
您可以在其Javadoc评论中描述该类的自用模式(满足让其他人知道的要求)。
这是留在这里的唯一选择。记录它或不提供默认实现。 所以是的,它的基本思想仍然适用,但是你的选择有限。