Java8中的接口
J.Bloch在为Java8中的接口,java,inheritance,java-8,Java,Inheritance,Java 8,J.Bloch在为Java6编写的有效Java中提到了以下内容(第17项): 如果您觉得必须允许从这样一个类继承,那么 合理的方法是确保该类从不调用 它的可重写方法并记录这一事实。换句话说,, 完全消除类自身对可重写方法的使用。 项目18: 如果您使用抽象类来定义类型,那么您就离开了程序员 谁想添加除了使用之外别无选择的功能 遗产由此产生的类功能较弱,也更脆弱 而不是包装类 虽然接口不允许包含方法实现, 使用接口定义类型并不妨碍您提供 对程序员的实施协助 现在在java8及其默认方法的实现中(使
Java6
编写的有效Java中提到了以下内容(第17项):
如果您觉得必须允许从这样一个类继承,那么
合理的方法是确保该类从不调用
它的可重写方法并记录这一事实。换句话说,,
完全消除类自身对可重写方法的使用。
项目18:
如果您使用抽象类来定义类型,那么您就离开了程序员
谁想添加除了使用之外别无选择的功能
遗产由此产生的类功能较弱,也更脆弱
而不是包装类
虽然接口不允许包含方法实现,
使用接口定义类型并不妨碍您提供
对程序员的实施协助
现在在java8
及其默认方法的实现中(使用接口中的其他方法),接口对于继承来说是危险的
例如:
public inteface MyInterface{
public void compute(Object o);
public default void computeAll(List<Object> oo){
for(Object o: oo)
compute(o); //self-use
}
}
公共接口MyInterface{
公共空间计算(对象o);
公共默认void computeAll(列表oo){
for(对象o:oo)
compute(o);//自用
}
}
因此,根据J.Bloch的说法,在我们尝试实现接口时可能会出现一些问题,因为:
公共类MyInterfaceCounter实现MyInterface{
私有整数计数=0;
@凌驾
公共void计算(对象o){
计数++;
}
@凌驾
公共无效计算机(列表oo){
count+=oo.size();//该死!!
MyInterface.super.computeAll(oo);
}
}
此外,我们不能将默认方法声明为
final
(正如我们可以对类所做的那样,这将使自用对重写器不太危险)。好的,从下面的答案看一下我们可以在这里应用什么:
你可以简单地避免自用
在这种情况下,你不能。在实现该接口时,唯一可依赖的选择(如果您想给出默认实现)是方法compute
。您必须使用它,否则就根本不提供实现
您可以将其中一个涉及的方法设置为final,这样它就不能被重写
这在接口中也不起作用
你可以让这门课成为期末考试,所以不能延长
这在接口中不起作用
您可以在Javadoc注释中描述类的自用模式(满足让其他人知道的要求)
这是唯一的选择。要么记录它,要么不给出默认实现。
是的,它的基本思想仍然适用,但是你的选择有点有限。过去的规则总是适用于未来的情况吗?很抱歉成为那个家伙。在我看来,这是一个好问题,但可能太受观点驱动了。@Mena可能,但我认为这个问题是关于在实现Java8接口时应该做的正确事情。我的第一个想法是使用默认方法是不好的。布洛赫说,其中一种方法是避免可重写方法的自我使用。我认为Java8实现者很清楚默认方法的这个陷阱。这就是为什么除了记录默认方法的工作之外,他们还记录默认方法的工作方式。例如,请参见Collection.removeIf(),它清楚地说明了该方法是如何实现的。接口的基本概念是声明将从其他对象访问的公共方法,因此定义公共方法以便仅在类内使用并允许其他人重写它是毫无用处的,简单地通过扩展它。出于这个原因,我们使用私有方法进行继承,或者您也可以将它们定义为public final
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);
}
}