Java 8中的接口

St.*_*rio 13 java inheritance java-8

J. Bloch在撰写的Effective Java中Java 6提到了以下内容(第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
   }
}
Run Code Online (Sandbox Code Playgroud)

因此,根据J. Bloch的说法,当我们尝试实现接口时,它可能会引入一些问题,因为:

  1. 覆盖这样的方法(类似于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);
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 客户端访问接口的内部,即他们必须知道默认实现.

在Java 8中如何处理它?Effective Java的规则是否适用仍然适用?

而且,我们不能将默认方法声明为final(因为我们可以对类进行声明,它会使自用对于重写器来说不太危险).

til*_*ois 3

好的,从您之前的问题中获取答案,看看我们可以在这里应用什么:

您可以简单地避免自用。

在这种情况下你不能。在实现该接口时,您唯一依赖的选择(如果您想提供默认实现)是 method compute。您必须使用它,否则根本不提供实现。

您可以将涉及的方法之一设置为最终方法,这样它就不能被覆盖。

这在界面中也不起作用。

您可以将课程定为期末课程,因此无法延长。

这在界面中不起作用。

您可以在其Javadoc注释中描述该类的自用模式(满足让其他人知道的要求)。

这是这里唯一的选择。要么记录下来,要么不给出默认实现。所以是的,它的基本思想仍然适用,但是您的选择有些有限。