Java 8 中的接口 [已关闭]

2022-09-04 23:19:37

J. Bloch在他的《Effective Java》中提到以下内容(第17项):Java 6

如果您认为必须允许从此类继承,一种合理的方法是确保该类永远不会调用其任何可重写的方法并记录此事实。换句话说,完全消除类对可重写方法的自我使用。

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

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

此外,我们不能将默认方法声明为(就像我们可以对类所做的那样,这将使自用对覆盖者来说不太危险)。final


答案 1

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

你可以简单地避免自用。

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

您可以将所涉及的方法之一设置为最终方法,因此无法覆盖它。

这在界面中也不起作用。

你可以使该类成为最终类,因此无法扩展它。

这在界面中不起作用。

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

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


答案 2

推荐