// codeart.ru / Работаем с кодом / Наследование против композиции, что предпочтительнее? Форум

Наследование против композиции, что предпочтительнее? rss подписка

Автор: Evgeniy Sergeev

Недавно, мне предложили провести серию небольших семинаров по объектно ориентированному программированию. Я согласился. И вот теперь пытаюсь накидать конспект лекции по инкапсуляции и наследованию.

Пока написал некоторые основные тезисы, которые хочу развить до полноценной лекции. Хотелось бы увидеть в комментариях ваше мнение о том, что написано.

Основная цель ООП заключается в том, чтобы код создаваемый в одном месте можно было использовать в разных местах программы. При этом сам код не дублируется. Для реализации этой цели у программиста есть два мощных метода — наследование и композиция. И у того и у другого метода есть как достоинства так и недостатки. Но тем ни менее злоупотребление наследованием в конечном счете может стоить разработчику гораздо дороже нежели использование композиции.

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

На практике, чтобы избежать зависимости от реализации, предпочтительнее наследовать абстрактные классы (или интерфейсы). Тогда класс-потомок может сам определить каким образом реализовать свою работу.

В противовес наследованию, часто используется другой метод — композиция.

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

Исходя из сказанного можно вывести два важных правила:

Первое правило: программируйте в соответствии с интерфейсом, а не реализацией.

Второе правило: предпочитаете инкапсуляцию наследованию.

Следование данным правилам, в конечном счете, позволит вам писать более гибкие программы.

P.S. запустил обсуждение наследование против композиции

  1. Немного о behaviour тестировании в TDD
  1. в контексте какого языка обсуждение?
    ведь очень важно наличие или отсутствие: method overloading, method mixing…

  2. dkrnl, мне кажется, что язык таки не очень важен. Не столько важна техническая реализация, сколько общая идея о том как должен быть построен код.

  3. Да нет, язык всё-таки важен. То, что композиция ВСЕГДА лучше наследования — это догма, которая не совсем верна. В таком языке как C++, имеющим множественное наследование и шаблоны, у композиции только один плюс: возможность изменять какие-то аспекты динамически. Если это не требуется, наследование может быть предпочтительнее.

  4. Anton, можете привести конкретный пример, когда наследование предпочтительнее композиции?

  5. Вот моя статья на хабре: http://habrahabr.ru/post/177447/

  6. Anton, спасибо. Ознакомился, в общем и целом согласен с твоими тезисами. ИМХО, здесь главное не заморачитваться сильно на подобные вопросы. Главное — решение задачи, которую поставил заказчик. Плохой код лучше чем никакой )

  7. Полностью согласен. Просто я против различных религиозных верований в разработке, коими являются и паттерны GoF. Иногда вера и убеждения часто становятся выше здравого смысла. И вместо того, чтобы развивать интуицию и писать код, исходя их неё и собственных выводов, разработчики часто слепо действуют шаблонам, причём в большинстве случаев «не в кассу»… Я ещё просто проработал лет 6 с молодыми разработчиками на C++, насмотрелся их кода, и у меня возникло стойкое желание отобрать у них всю литературу по паттернам на несколько лет :) Пока они к ней действительно не будут готовы…

  8. Вот, вот! Насчет интуиции очень правельная мысль. При написании кода в первую очередь руководствуюсь своими ощущениями, бывает так что вроде бы прозрачная и простая идея никак не ложится в код.
    И можно сколько угодно подгонять этот код под имеющуюся теорию (в том числе паттерны), а пока не изменишь саму идею ничего дельного не получается.

  9. Точно! Ещё вот работодателям бы это объяснить… Эмпирически развитая интуиция их мало волнует, зато вот паттерны на собеседованиях спрашивают почти всегда… И если человек сам может за минуту применить какое-то решение, но не знает при этом, что уже есть такой известный паттерн, и тем более, его название, то он очень рискует это собеседование провалить :) Когда-то программист бы сродни художнику… А сейчас методологии, методологии, методологии… А люди как гайки…

  10. Антон, работодатели тоже разные бывают. Я думаю, что если простым человечискми языком пояснить свою позицию, то адекватный человек поймет и примет правильное решение.

Leave a Reply

« »