Java 8中的接口

时间:2015-06-29 08:26:33

标签: java inheritance java-8

学家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的说法,当我们尝试实现接口时,它可能会引入一些问题,因为:

  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);
      }
    }
    
  2. 客户端访问接口的内部,即他们必须知道默认实现。

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

    此外,我们不能将默认方法声明为final(正如我们可以为类做的那样,它会使自用对于重写器来说不太危险)。

1 个答案:

答案 0 :(得分:3)

好的,请从your previous question获取答案,看看我们在这里可以应用的内容:

  

你可以简单地避免自我使用。

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

  

你可以让其中一个方法参与最终,因此无法覆盖。

这也不适用于界面。

  

你可以让班级成为最终版,因此无法扩展。

这在界面中不起作用。

  

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

这是留在这里的唯一选择。记录它或不提供默认实现。 所以是的,它的基本思想仍然适用,但是你的选择有限。