The important thing to keep in mind is that default methods don't have access to state, only to behaviour. It is actually a great place to define reasonable, default, behaviour.
Imagine you have an interface:
public interface Plant {
enum Pace { FAST, SLOW; }
void grow(Pace pace);
void growFast();
void growSlow();
}
It seems reasonable to provide a default behaviour:
default void growFast() { grow(Pace.FAST); }
default void growSlow() { grow(Pace.SLOW); }
This is a simplistic example but shows how default methods can be helpful. In this case, the way growSlow
or growFast
behaves is part of the interface contract so it makes sense to define their behaviour at the interface level.
However the interface makes no assumption about how the action "grow a plant" is implemented. That could be defined in an abstract class.