接口中的默认方法

default method in interfaces

有一段时间我一直对为什么我们需要接口中的默认方法感到困惑,今天我正在阅读它。虽然我的问题很少有人回答,但我仍然有一些疑问。

举个简单的例子,我有一个interface1。 Class A 和 class B 实现接口 1。 interface1 有一个方法 X。

interface interface1{
    void methodX();
}

class A implements interface1{
   @override
   public void methodX(){
      //something 
  };
}

class B implements interface1{
   @override
   public void methodX(){
      //something 
  };
}

据我了解,由于向 interface1 添加新方法 Y 会破坏 Class A 和 class B,因此引入了默认方法。这意味着现在我可以添加一个默认方法,而无需修改 Class A 和 Class B。这也意味着默认方法必须足够通用才能执行我们期望它执行的任何操作, 对于 class A 和 class B.

现在,让我们考虑一下,我们通常在接口中添加函数,以便我们可以通过覆盖它来为它们提供 class 特定的实现。所以基本上,如果我默认在接口中添加方法 Y,那么我会期望 class A 和 class B(或 class A/ClassB)覆盖该方法.

这意味着,我将修改 Class A/Class B 或两者。

这就是让我困惑的地方。这可以通过创建一个新接口并修改 1(或两者)class(es) 来实现该新接口(接口 2 扩展接口 1),然后在 [=29= 中提供相同的实现来处理].

interface interface2 extends interface1{
     void methodY();
}

class A implements interface2{
     @override
     public void methodY(){
         //something
     }
}

class B implements interface1{
   @override
   public void methodX(){
      //something 
  };
}

默认方法实际上如何帮助我们不修改实现它的 classes。

由于默认方法是在接口中定义的,它只能访问同样定义在同一接口中的实例方法。因此,它只能调用实现 类(在您的示例中 AB)实际提供的功能。

默认方法没有 "change" 类' 行为,它通过访问现有的、正确定义的行为来扩展它。

如果您要求所有实现 classes 覆盖新方法,那么它应该(如果没有有效的默认实现)不是默认方法。

但是,您所说的方法是创建一个新接口来扩展现有接口并使class希望覆盖新方法(s) 通过改变他们实现的接口类型会有问题,因为新方法是新接口的一部分,当你有 parent/base 接口类型时你不能访问它。

示例:

现有代码:

interface Base {
    void m1();
}
class A implements Base {
   @Override
   public void m1() {
      ....
   }
}
class B implements Base {
   @Override
   public void m1() {
      ....
   }
}

你创建如下界面

interface ExtendedBase extends Base {
    void m2();
}

只有 class A 想实施 m2。于是,就变成了

class A implements ExtendedBase {
   @Override
   public void m1() {
      ....
   }
   @Override
   public void m2() {
      ....
   }
}

到目前为止一切都很好。

当你有一个接受类型为 Base 的对象的方法时,你只能对其调用 m1(无论你传递类型为 A 还是 B)

void someMethod(Base base) {
    base.m1();
    //base.m2(); won't work
}

要在别处实际使用 m2,您需要将 Base 更改为 ExtendedBase,这意味着您不能再向其传递 B。所以,无论如何,你已经让所有 classes 实现了 m2

So basically, if I am adding a method Y in an interface as default, then I will expect class A and class B (or class A/ClassB) to override the method.

这个错了。

默认方法的思想是在不破坏与旧代码兼容性的情况下引入新方法。

无需修改现有实现 classes 即可使用新的默认方法。

This could have been handled by creating a new interface and modifying 1 (or both) class(es) to implement that new interface (interface 2 extending interface1), and then provide implementation for the same in the class.

然后您必须触摸/修改实现 class。这就是 default 方法试图避免的。

默认方法提供 "base" 一些行为的实现,这些行为可以由给定接口的现有方法组成。例如,您有一个带有 add 方法的接口。这足以为 addAll 行为提供默认实现:

default void addAll(Collection<? extends E> c) { for (E e : c) { add(e); } } 

另一个例子可以是List中的排序方法,可以通过提供的方法实现:get(int)set(int,E)size()。子类可能会覆盖此默认实现,以便根据特定列表属性提供更有效的排序。在 LinkedList 中,您可以利用 attaching/detaching 个节点(插入或删除节点时无需向右移动元素),在 ArrayList 中,您可以利用超快速访问元素的优势任何索引)。