В случае интерфейса все методы, которые определены в интерфейсе , должны быть реализованы классом, который его реализует.
Учитывая интерфейс A
interface A {
public void foo();
}
и класс B:
class B implements A {
}
он должен предоставить реализацию метода, определенного в интерфейсе:
class B implements A {
@Override
public void foo() {
System.out.println("foo");
}
}
В противном случае это ошибка времени компиляции. Теперь возьмите абстрактный класс с реализацией метода по умолчанию :
abstract class C {
public void bar() {
System.out.println("bar");
}
}
где класс, наследуемый от этого абстрактного класса, может выглядеть так:
class D extends C { }
без ошибок. Но он также может переопределить реализацию метода по умолчанию, если он склонен сделать это.
Что там говорил автор: если ваш API еще не стабилен и вам нужно адаптировать интерфейсы (да, абстрактные классы также являются интерфейсами (на языке ООП)), тогда абстрактный класс позволяет вам добавлять вещи без ломая классы, которые уже есть. Однако это справедливо только для неабстрактных методов. Если вы добавляете абстрактные методы, они все равно должны быть реализованы в каждом производном классе. Но, тем не менее, это может сделать вашу жизнь проще, если у вас есть API, который все еще развивается, и на нем уже есть много материала.