Да, носят чисто декларативный характер. Но в проектировании и при разработке в команде разработчиков очень сильно нужОн. Например, у нас есть некая сущность Тариф, от которой порождены конкретные реализации (Акционный, лимитный, безлимитный, специальный - не суть ) - их может что-то объединять/разделять. Поэтому, когда я пишу некий класс который как-то взаимодействует с Тарифом с определенным признаком, то я явно могу указать это создав специальный Интерфейс и запросить именно экземпляр класса конкретно этого интерфейса, а не родительского класса:
public function __construct(IDiscountByDay $Tariff){}
Далее уже сделать имплементацию этого интерфейса на всех наследниках класса Tariff где нужно, и не парится, что через какое-то время другой разработчик создаст новую реализацию тарифа и с твоего кода посыпятся баги