Я думаю, что это очень хороший подход. Не стыдитесь вопроса «без наследства». Большинство ООП не о наследовании. Наиболее важные аспекты - это инкапсуляция и полиморфизм, и вы их получили.
Можно утверждать (ну, я обычно утверждаю), что наследование необходимо только для статических языков, где вы должны как-то сказать компилятору, что эти два типа (классы) связаны, что у них есть что-то общее (общее предок), так что это может позволить полиморфизм. С динамическими языками OTOH компилятору все равно, а среда выполнения найдет общие черты без какого-либо наследования.
Еще один момент: если вам нужно какое-то наследование в некоторых местах (а оно отлично в некоторых случаях, например, в графических интерфейсах), часто вы обнаружите, что вы можете легко взаимодействовать между вашим «простым» объекты / классы и другие, более сложные и тяжелые. IOW: не пытайтесь найти структуру, которая отвечает всем вашим потребностям, и использовать ее для всего; вместо этого используйте тот, который вам удобнее в каждый момент, если он помогает с конкретной проблемой.