3

In the new java 8 specification language. They introduced the default modifier that allows the definition of a method in an interface.

My question is, does anyone have a good idea what's the best use case of this feature ?

Naili
  • 1,564
  • 3
  • 20
  • 27
  • This is a pretty broad question that doesn't have a specific answer so I won't provide one except as a comment, but one good example is when you want to add a method to an interface but don't wish to break any builds that use that interface already. – NESPowerGlove Apr 07 '14 at 17:19
  • Default implementations of interface methods, and allowing the addition of functionality without breaking previous interface implementations. – Dave Newton Apr 07 '14 at 17:25
  • I think the only real use for this is when you want to add new methods to an interface without break the code in any class the implements that interface. Think the some java core interface that need to add some more behaviors and can not break old code – luizcarlosfx Apr 07 '14 at 17:28
  • I asked a question on LinkedIn whether there was another use case besides adding functionality to existing interfaces. I got one response [here](https://www.linkedin.com/groups/Use-default-methods-in-interfaces-70526.S.5856459401652621312?trk=groups_search_item_list-0-b-ttl). That's just one responder's opinion, and I'm not endorsing it. – ajb Apr 07 '14 at 19:16

2 Answers2

6

To avoid breaking code - to support API evolution

Typical example is its use in the Iterable interface where a default stream() method has been introduced in Java 8. That way all Iterables inherit an already impemented stream method automagically. This gives support for API evolution without breaking the already existing code.

To define reasonable default behaviour

Let's say you create a new Collection framework, it would probably be reasonable to define:

interface MyCollection {
    int size();
    default boolean isEmpty() { return size() == 0; }
}

By doing that, you save the pain of having to redefine isEmpty exactly the same way in all implementing classes, while allowing a specific class to implement it differently if required.

That could be done in an abstract class but this enables you to remove one layer in the hierarchy and you get the inheritance flexibility of interfaces: a class can inherit several interfaces but can only inherit one abstract class.

See also: Interface with default methods vs Abstract class in Java 8.

Community
  • 1
  • 1
assylias
  • 321,522
  • 82
  • 660
  • 783
  • A good scenario here, but while we can override a default method, why we don't use an abstract class instead ? – Naili Apr 07 '14 at 17:42
  • 1
    @Naili you could use an abstract class instead: that's what has been done in the past! The default method alternative may remove one layer of inheritance and help you get rid of abstract classes layers - to be determined on a case by case basis. – assylias Apr 07 '14 at 17:49
  • 1
    @Naili You can only extend from *one* abstract class, while you can implement as many interfaces as you want. If both interfaces have different default implementations, then it can not be done with abstract classes anymore. – skiwi Apr 07 '14 at 17:56
  • It's clear now, because saying that it simply serves to create a default implementation of method is not enough. – Naili Apr 07 '14 at 18:03
1

Upgrade Elementary API

I believe that the main reason why they introduced this feature was to allow the upgrade of the very elementary interfaces - Collection, Iterable, Comparable, ... without inducing an incompatibility to already existing code - as assylias mentioned in his first paragraph.

Method Chaining

Furthermore, you may reach very interesting result by method chaining - methods which return the same type and you main chain they calls:

// Multiples of 5
final Predicate<Integer> fives = n -> n%5==0;
// Multiples of 7
final Predicate<Integer> sevens = n -> n%7==0;
// Multiples of 3
final Predicate<Integer> threes = n -> n%3==0;

// Multiples of 5 and 7 but not 3
final Predicate<Integer> compoundPredicate = fives.and(sevens).and(threes.negate());

This is possible due to extensive use of default methods:

@FunctionalInterface 
public interface Predicate<T> {
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        return (t) -> test(t) && other.test(t);
    }
    default Predicate<T> or(Predicate<? super T> other) {
        return (t) -> test(t) || other.test(t);
    }
    default Predicate<T> negate() {
        return (t) -> !test(t);
    } 
}

Get rid of artificial abstract classes and make room for real inheritance

As for the default behaviour, this will not only remove a completely artificial layer of abstract class (which would be created purely for the default behaviour), but it gives you the opportunity to introduce really useful abstract classes which model actual is-a relationships.

See the following example motivated by a game implementation. For most of the (monsters, isDead() is just a convenience method. But a zombie is never dead, isn't it. :)

enter image description here

enter image description here

enter image description here

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118