- Интерфейс - опишите поведение
- Класс - сделать поведение
Класс, расширяющий другой класс, наследует поведение. С другой стороны, реализация интерфейса просто говорит о том, что он должен вести себя так, но класс все еще должен знать, как это сделать.
Помимо ограничений одиночного наследования, код, использующий интерфейсы, легче реорганизовать и протестировать, например, обеспечить фиктивную реализацию для объекта доступа к базе данных в модульных тестах.
Итак, реальный ответ, это зависит от вашего дизайна.
Возможно, вы используете интерфейсы для описания поведения и абстрактные родительские классы для реализации поведения, которое может наследоваться подклассами. Или, может быть, подклассы настолько различны, что каждый реализует интерфейс по-своему.