Java 8允许在称为default methods的接口中默认实现方法。
我在什么时候使用那种接口默认方法,而不是抽象类(带有抽象方法)之间感到困惑。
那么什么时候应该使用默认方法的接口,什么时候应该使用抽象类(带有抽象方法)?抽象类在这种情况下仍然有用吗?
Java 8允许在称为default methods的接口中默认实现方法。
我在什么时候使用那种接口默认方法,而不是抽象类(带有抽象方法)之间感到困惑。
那么什么时候应该使用默认方法的接口,什么时候应该使用抽象类(带有抽象方法)?抽象类在这种情况下仍然有用吗?
当前回答
正如在其他回答中提到的,添加实现到接口的能力是为了在Collections框架中提供向后兼容性。我认为,提供向后兼容性可能是向接口添加实现的唯一好的理由。
否则,如果您将实现添加到接口,那么您就违反了最初添加接口的基本规律。Java是一种单一继承语言,不像c++允许多重继承。接口提供了支持多重继承的语言所具有的类型优势,而不会引入多重继承所带来的问题。
更具体地说,Java只允许实现的单一继承,但它允许接口的多重继承。例如,以下是有效的Java代码:
class MyObject extends String implements Runnable, Comparable { ... }
MyObject只继承了一个实现,但它继承了三个契约。
Java传递了实现的多重继承,因为实现的多重继承带来了许多棘手的问题,这些问题超出了本文的讨论范围。添加接口是为了允许合约的多重继承(又名接口),而不存在实现的多重继承问题。
为了支持我的观点,这里引用了Ken Arnold和James Gosling在《Java编程语言》(第4版)一书中的一句话:
Single inheritance precludes some useful and correct designs. The problems of multiple inheritance arise from multiple inheritance of implementation, but in many cases multiple inheritance is used to inherit a number of abstract contracts and perhaps one concrete implementation. Providing a means to inherit an abstract contract without inheriting an implementation allows the typing benefits of multiple inheritance without the problems of multiple implementation inheritance. The inheritance of an abstract contract is termed interface inheritance. The Java programming language supports interface inheritance by allowing you to declare an interface type
其他回答
虽然这是一个老问题,但让我也谈谈我的看法。
abstract class: Inside abstract class we can declare instance variables, which are required to the child class Interface: Inside interface every variables is always public static and final we cannot declare instance variables abstract class: Abstract class can talk about state of object Interface: Interface can never talk about state of object abstract class: Inside Abstract class we can declare constructors Interface: Inside interface we cannot declare constructors as purpose of constructors is to initialize instance variables. So what is the need of constructor there if we cannot have instance variables in interfaces. abstract class: Inside abstract class we can declare instance and static blocks Interface: Interfaces cannot have instance and static blocks. abstract class: Abstract class cannot refer lambda expression Interfaces: Interfaces with single abstract method can refer lambda expression abstract class: Inside abstract class we can override OBJECT CLASS methods Interfaces: We cannot override OBJECT CLASS methods inside interfaces.
最后,我要指出:
Default method concepts/static method concepts in interface came just to save implementation classes but not to provide meaningful useful implementation. Default methods/static methods are kind of dummy implementation, "if you want you can use them or you can override them (in case of default methods) in implementation class" Thus saving us from implementing new methods in implementation classes whenever new methods in interfaces are added. Therefore interfaces can never be equal to abstract classes.
正如在其他回答中提到的,添加实现到接口的能力是为了在Collections框架中提供向后兼容性。我认为,提供向后兼容性可能是向接口添加实现的唯一好的理由。
否则,如果您将实现添加到接口,那么您就违反了最初添加接口的基本规律。Java是一种单一继承语言,不像c++允许多重继承。接口提供了支持多重继承的语言所具有的类型优势,而不会引入多重继承所带来的问题。
更具体地说,Java只允许实现的单一继承,但它允许接口的多重继承。例如,以下是有效的Java代码:
class MyObject extends String implements Runnable, Comparable { ... }
MyObject只继承了一个实现,但它继承了三个契约。
Java传递了实现的多重继承,因为实现的多重继承带来了许多棘手的问题,这些问题超出了本文的讨论范围。添加接口是为了允许合约的多重继承(又名接口),而不存在实现的多重继承问题。
为了支持我的观点,这里引用了Ken Arnold和James Gosling在《Java编程语言》(第4版)一书中的一句话:
Single inheritance precludes some useful and correct designs. The problems of multiple inheritance arise from multiple inheritance of implementation, but in many cases multiple inheritance is used to inherit a number of abstract contracts and perhaps one concrete implementation. Providing a means to inherit an abstract contract without inheriting an implementation allows the typing benefits of multiple inheritance without the problems of multiple implementation inheritance. The inheritance of an abstract contract is termed interface inheritance. The Java programming language supports interface inheritance by allowing you to declare an interface type
有一些技术上的差异。与Java 8接口相比,抽象类仍然可以做更多的事情:
抽象类可以有构造函数。 抽象类更加结构化,可以保存状态。
从概念上讲,防御方法的主要目的是在Java 8中引入新特性(如lambda-functions)后实现向后兼容性。
抽象类比默认方法实现(如私有状态)要多得多,但从Java 8开始,无论何时您可以选择其中任何一种,都应该选择防御器(也就是私有状态)。默认)方法。
默认方法的限制是它只能通过调用其他接口方法来实现,而不能引用特定实现的状态。所以主要的用例是高级和方便的方法。
这个新特性的好处在于,以前您必须使用抽象类来实现方便的方法,从而将实现者限制为单一继承,现在您可以拥有一个真正干净的设计,只需要接口,并且强制程序员进行最少的实现工作。
向Java 8引入默认方法的最初动机是希望在不破坏任何现有实现的情况下,使用面向lambda的方法扩展集合框架接口。虽然这与公共图书馆的作者更相关,但您可能会发现相同的特性在您的项目中也很有用。您有一个集中的地方可以添加新的便利,而不必依赖于类型层次结构的其余部分。
关于你对…
那么什么时候应该使用默认方法的接口,什么时候应该使用抽象类?抽象类在这种情况下仍然有用吗?
Java文档提供了完美的答案。
抽象类与接口的比较:
Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation. However, with abstract classes, you can declare fields that are not static and final, and define public, protected, and private concrete methods. With interfaces, all fields are automatically public, static, and final, and all methods that you declare or define (as default methods) are public. In addition, you can extend only one class, whether or not it is abstract, whereas you can implement any number of interfaces.
它们各自的用例已经在下面的SE帖子中解释了:
接口和抽象类的区别是什么?
抽象类在这种情况下仍然有用吗?
是的。它们仍然有用。它们可以包含非静态的、非最终的方法和属性(受保护,除了公共之外还有私有),这即使是Java-8接口也不可能实现。