Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 -- interfaces with default methods vs abstract classes

I'm trying to come up with a complete answer to:

"why/when use an abstract class rather than an interface."

and looking for verification/suggestions on the following.

An answer to this is,

"to provide the implementation for some of it. Before the concrete classes come in to define the specific types, an abstract class, typically right below an interface in the inheritance hierarchy (as in many of its examples in the Java APIs) implements and pins down some common aspects of the structure that interface defines.

Another good reason to use an abstract class is that there is a clear logical hierarchy among the types. Abstract class has the use to organize that hierarchy while forcing, by being an abstract class rather than a concrete one, the instantiation of objects only on the concrete classes down below in this hierarchy where they are fully defined and thus are meaningful."

Then, in this context, comes the Q:

"since Java 8, interfaces can define default method implementations. Why wouldn't i write default method(s) in the interface instead of an abstract class that implements those method(s)? "

The answer to this would be:

" One reason is: interface methods are all public, field members are all constants (final & public). You may wanna restrict access privileges of methods and/or make them operate on non-constant state.

Another is: a descendant class can call upon the abstract class method(s) by super, while it can not do so on default interface methods. Also, the interface has no constructors to be invoked by the descendants.

The rest of the reasons are the same as those in pre-Java 8 above. "

Other than these above, why would i rather go for an abstract class than an interface especially now that i have the default interface methods since Java 8?

Please note: i've seen Java 8 default methods vs. non-abstract methods in abstract classes and Interface with default methods vs Abstract class in Java 8 along with some other useful discussions. This Q is rather about why chose an abstract class over an interface than the other way round.

TIA.

like image 244
Roam Avatar asked Nov 12 '14 20:11

Roam


3 Answers

Here are some reasons to choose an abstract class over an interface. The ones you list - private fields, etc., are some of the major ones. These are a few more subtle ones

  • Type clarity. You can only extend one class. This makes it clearer what your object is an how to use it.
  • The diamond problem. You have to implement all of the default methods in an interface to help avoid the diamond problem. If the interface is Collections, this can be a huge pain since there are a billion of them. With an abstract class, you only overwrite what you need to
  • In Java 8, there are lambda expressions, and the old routine of passing around an interface with a method to implement has been usurped. Still, when you see an interface with a default method, this can interpreted in ways you might not intend

Here's what Oracle has to say on the subject:

Which should you use, abstract classes or interfaces? Consider using abstract classes if any of these statements apply to your situation:

  • You want to share code among several closely related classes.
  • You expect that classes that extend your abstract class have many common methods or fields, or require access modifiers other than public (such as protected and private).
  • You want to declare non-static or non-final fields. This enables you to define methods that can access and modify the state of the object to which they belong.

In this article, Orace defends the distinction between the two type systems https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html

EDIT To clarify the "diamond problem" bullet The problem is described here (and many other places) http://www.lambdafaq.org/what-about-the-diamond-problem/

The problem occurs when you inherit from two places that declare the same method, and you have to pick one when resolving a function call. This was never an issue in Java 7-, since you could only extend one class and interfaces had no methods.

The resolution tactic now is a little complicated, but here is a good description of it: (from http://blog.loxal.net/2013/05/java-8-default-interface.html)

To address the diamond problem there is a precedence in which order an implementation is used: only if the class implements all default / optional methods of its interfaces, the code can be compiled and the implementations of this class are used. Otherwise the compiler tries to patch the missing implementation(s) with interface's default implementation. And if there are multiple default implementations of a method, then the diamond problem occurs and the compiler rejects the compilation. Also if the class implements an interface's default method, the implementation of the class will be used instead of interfaces's default implementation.

If you stick to abstract classes, you will never run into this problem. However, if your object is required to implement two interfaces (because it needs to be added to lists that are expecting those types, e.g.), and those interfaces have conflicting method signatures, you will wind up having to redefine a whole bunch of methods even if that means you're just making super calls, which sort of defeats the point of inheritance-based dynamic dispatch. It isn't a deal-breaker, but something to consider when structuring a complex Java project

like image 192
en_Knight Avatar answered Nov 15 '22 11:11

en_Knight


Interfaces with default methods can only define behaviour whereas abstract classes can have a state.

In other words you should use an abstract class if there is a member variable that you need to share across a subclass hierarchy (share here means that subclasses have access to it either directly if it is not private or through methods).

Another use case of abstract classes is if you want to override some of the Object methods such as equals or toString. That can't be done through default methods.

like image 35
assylias Avatar answered Nov 15 '22 12:11

assylias


short answer:

  1. a class may extend exactly one class.
  2. a class may implement any number of interfaces.
like image 25
DwB Avatar answered Nov 15 '22 11:11

DwB