И вот есть другие виджеты, у которых всё почти тоже самое, но некоторые аспекты поведения немного другие. Чего делать?
Ну, можно передавать аспекты поведения в качестве параметров в функцию. А можно записать в отдельный массив, и из функции обращаться к этому массиву. То есть вопрос не "зачем ООП", а "почему нельзя сделать чисто на функциях?".
Конструктор форм - это несколько функций ("Добавить поле", "Проверить форму перед отправкой"…) и массив с описаниями полей. Зачем здесь наследование?..
думаю тут FormElement и от него наследование - ComboBox, Input и т.д. У самого FormElement есть задачи удалить/переместить и всякие там параметры и стили