Has-A vs. Is-A ?

Тема в разделе "LANGS.C", создана пользователем NeuronViking, 13 янв 2011.

  1. NeuronViking

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    Поделитесь пожалуйста опытом, какими критериями выбора между наследованием и композицией вы пользуетесь для решения применить ли has-a или is-a отношения между классами? естественно хочется услышать о случаях, когда такое решение сделать не просто в силу "абстрактности" =) т.к. в совсем очевидных ситуациях (типа объект реального мира) выбор также очевиден.
     
  2. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    NeuronViking
    Я всегда провожу аналогию с реальным миром. Как правило, это всегда удаётся.
     
  3. reversecode

    reversecode Guest

    Публикаций:
    0
    иногда не всегда удается
    поэтому методом еволюции всегда можно прийти к оптимальному варианту

    ошибится сложно
    Код (Text):
    1. class children{}
    2. class room {}
    а вот
    Код (Text):
    1. class father {}
    2. class mother{}
    3. class child {}
    сложнее))
    ребенок может быть не от того папы, но папа будет влиять на его воспитание и ребенок может получить восптание и привычки нового папы
    ну итд))


    но гараздо более интерен вопрос как спроектировать так что бы не получился быдло код
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.321
    NeuronViking
    ну вообще это какой-то глобальный вопрос... а думаю, нужно более конкретно задать его... приведите пример нескольких классов, и можно будет обсудить то, как построить взаимоотношения между ними... мне на практике гораздо чаще приходилось делать интерфейсный класс и несколько наследников от него, разнящихся реализацей интерфейсных методов... с множественным наследованием как-то мало приходилось работать... вот кстати идеологически пример, в принципе позволяющий генерировать наследников разных родителей и наследников от наследников))):
    Код (Text):
    1. class mother {...};
    2. class mother1 {...} : public mother;
    3. class mother2 {...} : public mother;
    4. ...
    5. class father {...};
    6. class father1 {...} : public father;
    7. class father2 {...} : public father;
    8. ...
    9. class child {...} : public mother, public father;
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    NeuronViking

    Никаких общих правил нет. Все зависит от конкретной задачи.
     
  6. NeuronViking

    NeuronViking New Member

    Публикаций:
    0
    Регистрация:
    29 окт 2004
    Сообщения:
    476
    Адрес:
    где-то в Сиднее
    _DEN_

    я это знаю. именно поэтому и спрашиваю не о правилах, а прошу поделиться конкретным опытом в том или ином случае. если бы были правила, то жизнь была бы простой и веселой =)
     
  7. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    NeuronViking

    Чтобы ответить на твой вопрос, нужно не другим делиться своим опытом, а тебе рассказать о своей задаче.
     
  8. Damon

    Damon New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2010
    Сообщения:
    23
    Множественное наследование всегда ругали. ИМХО, правильно и по делу.

    Тупо наследовать, тоже не вариант. Наследование подразумевает (кроме совсем уж тривиальных случаев!) использование виртуальных методов.

    А с виртуальными методами, не все так просто, хотя и естественно :).
    Вот, где-то от сюда , и далее маленький тред на тему C++ vs. Java (типа, ява шустрее плюсов :derisive:.

    От себя добавлю, что подобное использование виртуальных методов тоже относится к "быдлокоду", ИМХО:
    Код (Text):
    1. class Toggle {
    2.      ....
    3.     virtual Toggle& activate();
    4.      ....
    5. };
    6.  
    7. class NthToggle : public Toggle {
    8.     Toggle& activate();
    9. };
    10.  
    11.     Toggle *toggle = new Toggle(val);
    12.      ....
    13.     NthToggle *ntoggle = new NthToggle(val, 3);
    Смысл их тогда делать виртуальными, эти методы? Все равно обращаешься не через указатель на предка, не проще ли тогда завести базового предка для обоих классов ( для общего кода обоих классов ), а эти классы независимо породить из него?

    Лично мне больше по душе подход Александреску, описанный в его буке "Современное проектирование на С++", где он описал вариант реализации паттерна "Стратегия", с использованием шаблонов. Не смотря, на то, что это реализуется через наследование от нескольких базовых классов, ИМХО, больше похож на композицию, когда терминальный класс порождается из нескольких тривиальных базовых, и не образуется сложных и разветвленных иерархий классов.
    Подобный подход, реализован и в STL. Не смотря, на то что там, например, итератор наследуется от базового класса, не уверен, что это можно назвать "классическим" наследованием.
    Собственно, сам сейчас ориентируюсь на подобное написание кода.

    Здесь-то, как раз, вопрос не в задаче, а в концепциях написания хорошего кода -- как писать, так "чтоб потом не было мучительно больно за бесцельно потраченное время" (С).

    А вообще, ИМХО, в рамках поставленного вопроса, абсолютно равноценно применить ли has-a или is-a отношения между классами. Если посмотреть на низком уровне то, фактически при композиции, полученный класс является фасадом для вложенного и его методы по большему счету пересылают значения вложенному классу ( может быть, с небольшой обработкой ), и при оптимизации будут проинлайнены ( при условии не виртуальности ). В случае же наследования, просто будет вызываться метод предка. Т.ч. оверхеда по коду можно избежать.

    А вообще, вот цитата с intuit.ru:
    В общем, реляционная алгебра и теория реляционных баз данных, оказывается существенно пересекается с ООП. :derisive:
     
  9. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Damon

    Если нет четкого понимания, то никакие чужие концепции тебе не помогут - пройдет пол года-год, и архитектура развалится по частям.
     
  10. Damon

    Damon New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2010
    Сообщения:
    23
    _DEN_
    Вообще-то, под концепциями я и понимаю "четкое понимание" (С), "разложенное по полочкам" (С)! :derisive:

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

    А вообще, "четкое понимание" (или концепции построения иерархии классов), в целом не зависит от конкретной задачи. Конкретная задача, лишь, вносит небольшие вариации, не более.
     
  11. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Damon

    Это большое заблуждение.
     
  12. Damon

    Damon New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2010
    Сообщения:
    23
    _DEN_
    Не вопрос, приведите пример!
    Интересно же знать, где я заблудился...
     
  13. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Damon

    Понимание того, как проектировать архитектуру в принципе, какими соображениями руководствоваться при выстраивании взаимоотношений между сущностями, и т.д. - это всего лишь, так скажем, средняя общеобразовательная школа. Для того, чтобы научиться проектировать качественные решения в конкретной области (игры, серверы, лексические анализаторы, веб-сервисы, компиляторы, и т.д.), нужно потратить довольно много времени, решая задачи в этой конкретной области.
     
  14. Damon

    Damon New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2010
    Сообщения:
    23
    _DEN_
    М-м-м... А Вам не кажется, что Вы чуть смешиваете понятия?
    Давайте для примера возьмем компилятор (почему бы и нет?).

    Как работает компилятор ( в первом приближении, подробнее -- книжка Ахо-Ульмана ):
    1) парсится исходник и разбивается на лексемы ( лексический анализ );
    2) поток лексем подвергается синтаксическому анализу и строится дерево разбора;
    3) к дереву применяются различные оптимизации;
    4) по дереву генериться код.

    Теперь вопрос -- каким боком перечесленные пункты ( реализация которых в сумме дает качественный компилятор ), относятся к ООП и композиции или наследованию классов? Я знаю компиляторы, вообще, без привлечения ООП написанные! GCC -- на C, к примеру. :derisive:

    Я к тому, что "архитектура, в принципе", может быть реализована и с помощью императивного программирования.
    Как пример крупных проектов -- ядро пингвина (врядли кто-то скажет, что мелкий проект).

    Т.ч., пожалуйста, не путайте алгоритм из конкретной предметной области и отношения классов. Это, как стратегия и тактика. Стратеги, лишь, отдают приказ, реализация же, целиком и полностью отдается на откуп тактикам!
     
  15. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Damon

    Это все пустое. Напишите хотя бы один компилятор от начала и до конца самостоятельно, тогда и поймете о чем я говорю.

    А я знаю программно-аппаратный комплекс, работающий с аптаймом в 34 года в полной изоляции, и написанный на ассемблере.

    Алгоритмы тут не при чем. Я говорю про архитектуру.
     
  16. Damon

    Damon New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2010
    Сообщения:
    23
    _DEN_

    Да я и так понимаю, о чем Вы говорите, мнение я высказал выше. :)

    Пока, никакой конкретики я от Вас не услышал, только общие фразы...

    Повторюсь, приведите конкретный пример, типа:
    "... Все хотели ( и по теории это было правильно! ) использовать наследование и тут прихожу я и говорю:
    -- Пацаны ( мужики, etc. [ не нужное зачеркнуть! ] )! А давайте будем использовать композицию классов!
    И использовали композицию и стало всем хорошо!"

    Или, наоборот наследование. Или, Вас не послушали и стало всем плохо... Или не Вас, а какого-либо гуру, не принципиально!

    В общем, давайте побольше конкретики! Правда же интересно, где я заблуждаюсь.
     
  17. cupuyc

    cupuyc New Member

    Публикаций:
    0
    Регистрация:
    2 апр 2009
    Сообщения:
    763
    И почему я упорно не хочу в это верить? Что под этим подразумевается? Гoвнoкoд на С++ работает в 20 раз медленнее, чем в жабе? Давайте свой тест проведём, потому что у меня уж оооооочень сильные сомнения - пока сам ни увижу - не поверю.
     
  18. krabz

    krabz New Member

    Публикаций:
    0
    Регистрация:
    26 май 2010
    Сообщения:
    135
    Да всё это фигня по-моему концепции эти, как средняя температура по больнице. Это катит чтобы книжки писать или бабло выбивать под супер-пупер концепции. Если ты врубился в предметную область, то понимаешь какие объекты как соотносятся. Если нет, то не помогут концепции - всё равно ошибёшься.
     
  19. Damon

    Damon New Member

    Публикаций:
    0
    Регистрация:
    14 мар 2010
    Сообщения:
    23
    cupuyc

    Там чуть ниже по треду я высказал свои соображения.
    Фактически, если ставить компиляторы в одинаковое положение, то видно, что ява проигрывает плюсам при вызове виртуальных методов в 2 раза -- см. на графике "клиентскую яву".

    Далее по коду возникает вопрос, если тестировать вот такой код, сумеет ли ява оптимизировать его:

    Код (Text):
    1.     Toggle *toggle = new Toggle(val);
    2.      ....
    3.     toggle = new NthToggle(val, 3);
    (это плюсовый код, для явы искать не охота, но там идентично будет!)

    ИМХО, это более корректный вариант вариант тестирования виртуальных методов!
     
  20. reversecode

    reversecode Guest

    Публикаций:
    0
    согласен
    только звучит это не так),

    звучит это так
    что бы решать конкретную задачу в какой то области, нужно досконально разбиратся(быть специалистом) в этой области


    то что ява быстрее С++ придумали жависты))