Java 8允许在称为default methods的接口中默认实现方法。
我在什么时候使用那种接口默认方法,而不是抽象类(带有抽象方法)之间感到困惑。
那么什么时候应该使用默认方法的接口,什么时候应该使用抽象类(带有抽象方法)?抽象类在这种情况下仍然有用吗?
Java 8允许在称为default methods的接口中默认实现方法。
我在什么时候使用那种接口默认方法,而不是抽象类(带有抽象方法)之间感到困惑。
那么什么时候应该使用默认方法的接口,什么时候应该使用抽象类(带有抽象方法)?抽象类在这种情况下仍然有用吗?
当前回答
Remi Forax规则是不要用抽象类进行设计。你用界面来设计你的应用。无论Java的版本是什么,无论语言是什么。它以SOLID原理中的界面分离原理为依据。
稍后您可以使用抽象类来分解代码。现在有了Java 8,你可以直接在界面中完成。这只是个设施,仅此而已。
其他回答
有一些技术上的差异。与Java 8接口相比,抽象类仍然可以做更多的事情:
抽象类可以有构造函数。 抽象类更加结构化,可以保存状态。
从概念上讲,防御方法的主要目的是在Java 8中引入新特性(如lambda-functions)后实现向后兼容性。
本文将对此进行描述。想想forEach of Collections。
List<?> list = …
list.forEach(…);
The forEach isn’t declared by java.util.List nor the java.util.Collection interface yet. One obvious solution would be to just add the new method to the existing interface and provide the implementation where required in the JDK. However, once published, it is impossible to add methods to an interface without breaking the existing implementation. The benefit that default methods bring is that now it’s possible to add a new default method to the interface and it doesn’t break the implementations.
虽然这是一个老问题,但让我也谈谈我的看法。
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.
每当我们在抽象类和接口之间做出选择时,我们总是(几乎)选择默认方法(也称为防御器或虚拟扩展)。
Default methods have put an end to classic pattern of interface and a companion class that implements most or all of the methods in that interface. An example is Collection and AbstractCollection. Now we should implement the methods in the interface itself to provide default functionality. The classes which implement the interface has choice to override the methods or inherit the default implementation. Another important use of default methods is interface evolution. Suppose I had a class Ball as: public class Ball implements Collection { ... }
现在在Java 8中引入了一个新特性流。我们可以通过使用添加到接口的stream方法来获取流。如果stream不是默认方法,那么Collection接口的所有实现都将中断,因为它们不会实现这个新方法。向接口添加非默认方法与源不兼容。
但是假设我们不重新编译这个类,而是使用一个包含这个类Ball的旧jar文件。如果没有这个缺失的方法,类将很好地加载,可以创建实例,似乎一切都在正常工作。但是如果程序在Ball实例上调用stream方法,我们将得到AbstractMethodError。因此,使方法默认解决了这两个问题。
Java 9甚至在接口中提供了私有方法,可以用来封装提供默认实现的接口方法中使用的公共代码逻辑。
如本文所述,
Java 8中的抽象类与接口
After introducing Default Method, it seems that interfaces and abstract classes are same. However, they are still different concept in Java 8. Abstract class can define constructor. They are more structured and can have a state associated with them. While in contrast, default method can be implemented only in the terms of invoking other interface methods, with no reference to a particular implementation's state. Hence, both use for different purposes and choosing between two really depends on the scenario context.