Я не отвечу тебе как оно внутри в симфони работает, но попробую добавить кое-что по интерфейсам
Интерфейс в общем случае это контракт, похожий на тот, что дают тебе на работе, когда принимают тебя.
Их не заполняют кодом, они как бы являются соглашением сторон - в нашем случае двух классов - о том, что то, что "прокидывается через интерфейс" обязательно умеет то, что написано в контракте, иначе программа не компилируется и не может быть выполнена.
С точки зрения управляющего зависимостями интерфейс это всего лишь название. Такое же как просто строка "апп.модульВася". Дальше сие пробросится через конструктор, который уже по логике ПХП проверит, то что было создано и подсунуто по этому названию - умеет ли то, что написано в интерфейсе? Нет? Ошибка. Кроме того сама пхп ещё до момента создания обьектов когда ты пишешь implements Интерфейс проверяет - умеет ли класс то, что он имплементит - тут как бы двойная связка
Интерфейс это всего лишь соглашение сторон, с другой стороны - интерфейс - это мощная гарантия умения делать что-либо. То есть не важно как называется обьект "гриша.модуль", "петя.суперМодуль" или "вася.гиперМодуль" - они должны уметь раз, два, три. Таким образом мы можешь прибить контракт к исполнителям, и потом тихонько подменить один на другой, чтобы никто не заметил и ничего не сломалось.
Ты можешь и просто создать некий класс, приняв для себя что "пока что мне хватит его, менять я его не собираюсь" - таким образом модуль разбирающийся с тем какой класс от кого зависит - просто выполнит инструкцию new ЧтоТо() и подкинет параметры (рекурсивно) которые ты указал. Это могут быть вещи которые ты явно укажешь в конфиге, а могут быть точно такие же модули, как тот, который сейчас собирается.
То есть управляшка зависимости создает обьект, читая его конструктор, и пытается по указанным типам данных подкинуть туда то, что можно создать. Что создать нельзя - она ругается, дескать - укажи это в конфигурации или передай вручную в момент создания. Но так как в симфони не принято создавать обьекты и обращаться к управляющему зависимостями напрямую - оно работает само, а если какой-то параметр заполнить нечем - ругается.