一段时间以来,我一直对为什么我们需要接口中的默认方法感到困惑,今天我正在阅读它。即使我的问题很少回答,我仍然有一些疑问。
让我们举一个简单的例子,我有一个interface1。 A类和B类实现interface1。 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将破坏A类和B类,因此引入了默认方法。这意味着现在我可以添加一个默认方法,而无需修改A类和B类。这也意味着该默认方法必须具有足够的通用性,才能对A类和B类都执行我们期望的操作。
现在,让我们考虑一下,我们通常在接口中添加函数,以便我们可以通过重写功能为它们提供特定于类的实现。因此,基本上,如果我在默认情况下在接口中添加方法Y,则我希望类A和类B(或类A / ClassB)重写该方法。
这意味着,我将同时修改A类/ B类或两者。
这就是令我困惑的地方。可以通过创建一个新接口并修改1个(或两个)类以实现该新接口(接口2扩展interface1),然后在该类中为该接口提供实现来解决此问题。
interface interface2 extends interface1{
void methodY();
}
class A implements interface2{
@override
public void methodY(){
//something
}
}
class B implements interface1{
@override
public void methodX(){
//something
};
}
默认方法实际上如何帮助我们不修改实现它的类。
答案 0 :(得分:2)
默认方法提供某些行为的“基础”实现,这些行为可以由给定接口上的现有方法组成。例如,您有一个使用add
方法的接口。这足以为addAll
行为提供默认实现:
default void addAll(Collection<? extends E> c) { for (E e : c) { add(e); } }
另一个示例可以是List
中的sort方法,可以通过以下提供的方法来实现:get(int)
,set(int,E)
,size()
。子类可能会覆盖此默认实现,以便基于特定列表属性提供更有效的排序。在LinkedList
中,您可以利用附加/分离节点的优势(在插入或删除节点时无需在右侧移动元素),在ArrayList
中,您可以利用对任何索引的元素的超快速访问)。
答案 1 :(得分:1)
由于在接口中定义了默认方法,因此它只能访问也在同一接口中定义的实例方法。因此,它只能调用实现类实际提供的功能(在您的示例A
和B
中)。
默认方法不会“更改”类的行为,而是通过访问现有的,正确定义的行为来扩展它。
答案 2 :(得分:1)
如果您强制所有实现类覆盖新方法,则它(如果没有有效的默认实现)应该不是默认方法。
但是,您刚才所说的方法是创建一个扩展现有接口的新接口,并通过更改实现的接口类型,使希望的类覆盖新方法由于新方法是新接口的一部分,因此会出现问题,如果您具有父/基本接口类型,则无法访问它。
示例:
现有代码:
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();
}
只有类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
传递给它。因此,无论如何,您已经使所有类都实现了m2
。
答案 3 :(得分:1)
因此,基本上,如果我默认在接口中添加方法Y,那么我期望类A和类B(或类A / ClassB)将覆盖该方法。
这是错误的。
默认方法的想法是引入新方法,而不会与旧代码兼容。
现有的实现类无需修改即可使用新的默认方法。
这可以通过创建一个新接口并修改1个(或两个)类以实现该新接口(接口2扩展interface1),然后在该类中为该接口提供实现来解决。
然后,您必须触摸/修改实现类。这就是default
方法要避免的方法。