Java是否计划使用默认方法(java8)替代抽象类?

Ahm*_*aya 2 java abstract-class interface java-8 default-method

Java有计划default method替代 Abstract Class吗?我找不到使用默认方法而不是抽象的真实案例?

Hol*_*ger 8

没有这样的计划,你可以从比较已经记录的意图中得出这些计划,这些意图与这样一个计划的含义不同:

斯图尔特马克斯写道:

主要目标是允许界面演变,即添加新方法.如果将新方法添加到接口,则实现该接口的现有类将缺少实现,这将是不兼容的.为了兼容,实现必须来自某个地方,因此它是由默认方法提供的.

...

Java接口的主要目的是指定任何类都可以实现的契约,而不必改变它在类层次结构中的位置.确实,在Java 8之前,接口纯粹是抽象的.但是,这不是接口的基本属性.即使包含默认方法,其核心接口仍然在实现类上指定合同.实现类可以覆盖默认方法,因此该类仍然可以完全控制其实现.(另请注意,默认方法不能是最终方法.)

Brian Goetz写道:

向接口添加默认方法的近似原因是支持接口演进,......

以下是一些完全符合设计目标的用例:

  • 界面演变.在这里,我们向现有接口添加一个新方法,该接口在该接口上的现有方法方面具有合理的默认实现.一个例子是将forEach方法添加到Collection,其中默认实现是根据iterator()方法编写的.

  • "可选"方法.在这里,接口的设计者说"如果他们愿意接受需要的功能限制,那么实现者就不需要实现这种方法".例如,Iterator.remove给出了抛出的默认值UnsupportedOperationException; 由于绝大多数实现Iterator都有此行为,因此默认情况下此方法基本上是可选的.(如果行为AbstractCollection表示为默认值Collection,我们可能会对mutative方法执行相同的操作.)

  • 方便的方法.这些方法严格来说是为了方便,通常也是根据类中的非默认方法实现的.logger()您的第一个示例中的方法是对此的合理说明.

  • 组合子.这些是基于当前实例实例化接口的新实例的组合方法.例如,方法Predicate.and()或是Comparator.thenComparing()组合子的例子.

请注意,这些不是针对抽象类的主域,例如提供框架实现.除了技术差异之外,抽象类在语义上是不同的,因为它们承担有关如何实现功能的设计决策,即使使用default方法,接口也不应该.例如,一个众所周知的例子是List接口,其中存在两个根本不同的抽象类,AbstractList并且接口不应该排除AbstractSequentialList子类的选择或者实现List完全不同的子类.因此,List接口定义了契约,并且永远不能替代抽象类,后者提供特定的基本实现.


Stu*_*rks 6

其他答案以及其他材料的链接已经充分涵盖了接口和抽象类之间的技术差异.没有完全覆盖的是为什么使用一个而不是另一个.

考虑在Java中使用类或接口的两种不同方式:作为调用者子类.调用者有一个对象引用,可以通过该引用调用public方法和访问public字段.子类加密器还可以访问,调用和覆盖protected超类的成员.类可以有protected成员,但接口不能.

一个常见的问题似乎是,既然我们有默认方法,为什么我们需要抽象类?默认方法是界面向呼叫者呈现的部分.protected调用者无法使用类的方法; 它只适用于子类.因此,如果要与子类共享实现,则使用类(或抽象类)并定义protected成员和字段.

protected机制允许类与子类通信器进行通信,这与它与调用者的通信方式不同.

但是OP提出了相反的问题:为什么人们会优先使用默认方法而不是抽象类?在您实际可以选择的情况下(即,您的抽象不需要状态或受保护的方法,或抽象类具有的接口不具有的任何东西),具有默认方法的接口远比抽象类更少约束.你只能从一个类继承; 你可以从许多接口继承.因此,使用默认方法的接口可以像无状态特征或mixin一样,允许您从多个接口继承行为.

鉴于接口和抽象类用于不同的目的,没有计划删除或替换任何东西.


Ada*_*ion 5

引入接口中的默认方法的原因之一是允许向JDK接口添加新方法.

使用特定版本的接口编译类后,如果没有此功能,则不能向此接口添加新方法.使用接口中的默认方法,可以更改功能接口.


biz*_*lop 5

默认方法不能替代抽象类,因为抽象类可以(并且经常)具有字段.接口只能包含行为,而不能包含状态,这在将来不太可能改变,因为Java中的多重状态继承(正确或错误地)被视为邪恶.

他们也可以有final方法,这是你无法用default方法模仿的另一种方法.

如果有的话,具有默认方法的接口类似于特征而不是抽象类,但匹配并不完美.使用接口作为特征是必须非常小心地完成并且知道它们带来的限制.(例如任何实现类都可以覆盖default方法,可能会破坏特征.)

更多关于这里.

  • @Peter Lawrey:接口中的`private`方法只能帮助在不同的always-`public``default`或`static`方法之间共享代码.这与具有访问控制的发布方法不同,即声明它们是`protected`或package-private.请注意,接口中对`private`方法的支持已经在Java 8中已经成为事实,因为lambda表达式被编译成`private`方法,这也适用于`default`或`static`接口方法中包含的lambda表达式. (5认同)
  • @Peter Lawrey:这就是我想说的; 它们不会改变,界面如何从外面看起来像. (3认同)
  • Java 9将具有私有方法(如抽象类所做),尽管Java 8没有. (2认同)
  • 接口中的@Holger私有方法将允许代码在公共方法之间共享并从中提取以简化它们. (2认同)