Abstract Class VS Interface in Java

What is the difference between an interface and abstract class?

Interfaces

An interface is a contract: The person writing the interface says, "hey, I accept things looking that way", and the person using the interface says "OK, the class I write looks that way".

An interface is an empty shell. There are only the signatures of the methods, which implies that the methods do not have a body. The interface can't do anything. It's just a pattern.

For example (pseudo code):

// I say all motor vehicles should look like this:
interface MotorVehicle
{
void run();

int getFuel();
}

// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{

int fuel;

void run()
{
print("Wrroooooooom");
}

int getFuel()
{
return this.fuel;
}
}

Implementing an interface consumes very little CPU, because it's not a class, just a bunch of names, and therefore there isn't any expensive look-up to do. It's great when it matters, such as in embedded devices.


Abstract classes

Abstract classes, unlike interfaces, are classes. They are more expensive to use, because there is a look-up to do when you inherit from them.

Abstract classes look a lot like interfaces, but they have something more: You can define a behavior for them. It's more about a person saying, "these classes should look like that, and they have that in common, so fill in the blanks!".

For example:

// I say all motor vehicles should look like this:
abstract class MotorVehicle
{

int fuel;

// They ALL have fuel, so lets implement this for everybody.
int getFuel()
{
return this.fuel;
}

// That can be very different, force them to provide their
// own implementation.
abstract void run();
}

// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
void run()
{
print("Wrroooooooom");
}
}

Implementation

While abstract classes and interfaces are supposed to be different concepts, the implementations make that statement sometimes untrue. Sometimes, they are not even what you think they are.

In Java, this rule is strongly enforced, while in PHP, interfaces are abstract classes with no method declared.

In Python, abstract classes are more a programming trick you can get from the ABC module and is actually using metaclasses, and therefore classes. And interfaces are more related to duck typing in this language and it's a mix between conventions and special methods that call descriptors (the __method__ methods).

As usual with programming, there is theory, practice, and practice in another language :-)

What is the difference between abstract classes and interfaces in Java 8 and beyond?

The main difference between an abstract class and interface in Java 8 is the fact that an abstract class is a class and an interface is an interface.

A class can have a state which can be modified by non-abstract methods but an interface cannot have the state because they can't have instance variables.

The second difference is that an interface cannot have a constructor even in Java 8 but you may remember that abstract class always has a constructor in Java.

In reality, default or defender methods are introduced to maintain backward compatibility and same time making Collection API more suitable to be used inside key Java 8 features like lambda expressions.

Without adding default methods, it wasn't possible to declare any new method on existing interface in Java without breaking all classes which implement it, but because of default method, you can now better evolve your API.

They defend your code against implementing new methods hence they are also called defender methods.

Fundamental difference between interface and abstract class in Java 8

Interfaces still can't have any state. Interfaces still can't have any final method, which means that any implementation can override all its default methods. And interfaces still can't have any constructor.

You can still implement multiple interfaces, even if they have default methods with the same signature. You can't extend multiple classes (abstract or not).

Java 8 -- interfaces with default methods vs abstract classes

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



Related Topics



Leave a reply



Submit