Раньше interface не имел реализации и нам приходилось реализовывать абстрактные классы. Но сейчас, а конкретно, начиная с 'Java8', interface может иметь реализацию. Зачем так поступили? В чём здесь выигрыш? Какие преимущества дает интерфейс, имеющий реализацию? И главное, в чем тогда смысл использования абстрактных классов, если интерфейс может содержать реализацию методов?
-
2@elik например у вас есть листенер на 20 полей и всех достало писать 20 пустых методов (когда нужен 1 только). А делать классом нельзя - и семантика не та и конфликты наследования. А пустая реализация - то что надо. – pavel Oct 12 '17 at 12:50
-
1см. также : https://ru.stackoverflow.com/questions/621959 – Nofate Oct 12 '17 at 13:03
-
1Возможный дубликат вопроса: Отличия абстрактного класса от интерфейса (abstract class and interface) – Roman C Feb 05 '22 at 09:36
1 Answers
Интерфейс описывает только поведение (методы) и не может иметь состояние (поля), абстрактный класс - может.
В случае с default-методами, поведение может быть не только описано, но и реализовано. Однако по-прежнему без доступа к состоянию.
В Java 8 default-методы были добавлены во многом ради Stream API. Это позволило добавить методы spliterator() и stream() всем коллекциям, которые были написаны до появления Stream API, не затрагивая их реализации:
public interface Iterable<T>
// ...
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
public interface Collection<E> extends Iterable<E> {
// ...
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
}
Как видите, default-методы тут ведут себя как миксины, оборачивающие некоторую стороннюю реализацию (Spliterators, StreamSupport) и превращающую ее в честные методы коллекций.
Пример из жизни. Есть интерфейс доступа к данным, который может иметь разные реализации:
public interface Repository {
Foo getFooWithTimeout(int id, int timeout);
// ...
}
И хочется иметь его сокращенную версию какого-то метода со значениями параметров по-умолчанию. Тогда достаточно просто обернуть существующий метод default-методом:
public interface Repository {
Foo getFooWithTimeout(int id, int timeout);
default Foo getFoo(int id) {
return getFooWithTimeout(id, 0);
}
// ...
}
Мы расширили контракт всех реализаций интерфейса Repository новым методом, при этом никто не пострадал нам не пришлось вторгаться в реализации.
- 34,603
-
Хотел бы добавить, что default-методы - это, еще и шаг в сторону множественного наследования. В Java, класс не может наследоваться от нескольких абстрактных классов, а реализовывать несколько интерфейсов - может. – Sergi Oct 12 '17 at 12:59