What are the differences between abstract classes and interfaces in Java 8?
Asked Answered
H

5

68

In Java there used to be a subtle but important difference between abstract classes and interfaces: default implementations. Abstract classes could have them, interfaces could not. Java 8 though introduces default implementations for interfaces, meaning this is no longer the critical difference between an interface and an abstract class.

So what is?

As best as I can tell, the only remaining difference (besides perhaps some under the hood efficiency stuff) is that abstract classes follow traditional Java single-inheritance, whereas interfaces can have multiple-inheritance (or multiple-implementation if you will). This leads me to another question -

How do the new Java 8 interfaces avoid the diamond Problem?

Humanist answered 23/3, 2014 at 13:25 Comment(3)
have you read What about the diamond problem??Americanist
In your link it states: "Java 8 introduces default methods on interfaces. If A,B,C are interfaces, B,C can each provide a different implementation to an abstract method of A, causing the diamond problem. Either class D must reimplement the method (the body of which can simply forward the call to one of the super implementations), or the ambiguity will be rejected as a compile error. [6]"Carilla
@Americanist I have not, thank you!Humanist
C
70

Interfaces cannot have state associated with them.

Abstract classes can have state associated with them.

Furthermore, default methods in interfaces need not be implemented. So in this way, it will not break already existing code, as while the interface does receive an update, the implementing class does not need to implement it.
As a result you may get suboptimal code, but if you want to have more optimal code, then your job is to override the default implementation.

And lastly, in case a diamond problem occurs, then the compiler will warn you, and you will need to choose which interface you want to implement.

To show more about the diamond problem, consider the following code:

interface A {
    void method();
}

interface B extends A {
    @Override
    default void method() {
        System.out.println("B");
    }
}

interface C extends A { 
    @Override
    default void method() {
        System.out.println("C");
    }
}

interface D extends B, C {

}

Here I get the compiler error on interface D extends B, C, that:

interface D inherits unrelated defaults for method() form types B and C

The fix is:

interface D extends B, C {
    @Override
    default void method() {
        B.super.method();
    }
}

In case I wanted to inherit the method() from B.
The same holds for if D were a class.

To show even more about the difference between interfaces and abstract classes in Java 8, consider the following Team:

interface Player {

}

interface Team {
    void addPlayer(Player player);
}

You can in theory provide a default implementation of addPlayer such that you can add players to for example a list of players.
But wait...?
How do I store the list of players?
The answer is that you cannot do that in an interface, even if you have default implementations available.

Cannikin answered 23/3, 2014 at 13:28 Comment(1)
The example with overriding methods is not specific to the diamond problem. Nothing changes if you remove interface A.Artery
D
19

There have been some very detailed answers, but they seem to be missing one point that I at least consider as one of the very few justifications to have abstract classes at all:

Abstract classes can have protected members (and members with default visibility). Methods in interfaces are implicitly public.

Dominions answered 28/3, 2014 at 19:29 Comment(2)
Oh yeah, also true. However that hasnt changed since Java 7Humanist
@Dgrin91 Yes. But now, in Java 8, default methods can be used in many places where one would otherwise possibly have used an abstract class (with exactly this method being non-abstract). Formerly, an imporant justification to have abstract classes was to implement common, reusable methods. This can now be solved with default methods in many (not all) cases. So I think the visibility aspects become more important.Dominions
A
9

The definition of the diamond problem is a vague. There are all kinds of issues that can occur with multiple inheritance. Fortunately, most of them can be easily detected at compile-time, and the programming languages support simple solutions to work around these issues. Most of these problems are not even specific to the diamond problem. For example, conflicting definitions of methods can also occur without diamonds:

interface Bar {
    default int test() { return 42; }
}
interface Baz {
    default int test() { return 6 * 9; }
}
class Foo implements Bar, Baz { }

The specific problem with diamonds is the question of inclusive vs. exclusive. If you have a type hierarchy where B and C derive from A, and D derives from B and C, then the question is:

  • is D a B *and* a C (i.e. one type of A), or
  • is D a B *or* a C (i.e. two types of A).

Well, in Java 8 the type A has to be an interface. So it makes no difference, because interfaces have no state. It doesn't matter, that interfaces can define default methods, since they also have no state. They can invoke methods that have direct access to state. However, these methods are always implemented based on single inheritance.

Artery answered 23/3, 2014 at 13:27 Comment(5)
@LeonardBrünings, another answer clarified my doubt. Thanks.Malaya
Not having member variables does not solve the diamond problem - you could still have two conflicting implementations of the same method without them using any internal state. The diamond problem is solved by simply not allowing a class to implement two interfaces with conflicting default implementations.Baum
Can “doubt” sometimes mean “question”?Gagman
@Philipp: You can also have two conflicting methods without diamonds. The OP specifically asked for the diamond problem. And the important thing about diamonds is state.Artery
@PradeepSimha Can you link to the answer that clarified this for you? I still see ways that introducing default methods can break existing code.Jonniejonny
B
5

Now that interfaces can contain executable code, lots of use-cases for abstract classes are taken over by interfaces. But abstract classes can still have member variables, while interfaces can't.

The diamond problem is avoided by simply not allowing a class to implement two interfaces when both interfaces provide a default implementation for the same method with the same signature.

Baum answered 23/3, 2014 at 13:35 Comment(0)
E
4

Java 8 though introduces default implementations for interfaces, meaning this is no longer the critical difference between an interface and an abstract class.

Still there are few more critical differences. Refer to this post:

Interface with default methods vs Abstract class in Java 8

How do the new Java 8 interfaces avoid the diamond Problem?

Case 1: You are implementing two interfaces, which have same default method, you have to resolve the conflict in your implementation class

interface interfaceA{
    default public void foo(){
        System.out.println("InterfaceA foo");
    }
}
interface interfaceB{
    default public void foo(){
        System.out.println("InterfaceB foo");
    }
}
public class DiamondExample implements interfaceA,interfaceB{
    public void foo(){
        interfaceA.super.foo();
    }
    public static void main(String args[]){
        new DiamondExample().foo();
    }
} 

Above example produce below outout:

InterfaceA foo

Case 2: You are extending a base class and implementing an interface with default method. Compiler resolves the diamond problem for you and you don't have to resolve it as in first example.

interface interfaceA{
    default public void foo(){
        System.out.println("InterfaceA foo");
    }
}

class DiamondBase {
    public void foo(){
        System.out.println("Diamond base foo");
    }
}

public class DiamondExample extends DiamondBase implements interfaceA{

    public static void main(String args[]){
        new DiamondExample().foo();
    }
}

Above example produce below output:

Diamond base foo
Entresol answered 20/11, 2016 at 2:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.