На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
  
> Инкапсуляция vs Агрегирование , размышления в различных реализациях (языках программирования)
   
Что считаете лучшим?
Гости не могут просматривать результаты голосования.
Гости не могут голосовать 
    Дабы привнести нечто техническое давайте обсудим сабж?
      Фигня. Предлагаю опрос - что лучше, танк или вертолёт :yes:

      Добавлено
      К тому же причём вообще инкапсуляция? Обычно агрегированию противопоставляют наследование.
        Цитата OpenGL @
        К тому же причём вообще инкапсуляция? Обычно агрегированию противопоставляют наследование.

        WTF? Инкапсуляция предполагает объединение данных, ровно и как агрегирование. Хочется тему за наследование (полагаю про виртуализацию, сиречь полиморфизм) - делай тему! Тут только про данные.
          JoeUser,
          Цитата
          В первом сообщении - список параметров, по которым идет сравнение.

          Ну и было бы неплохо, если бы ты дал определения :)
            +1. У тебя, очевидно, какое-то своё понимание инкапсуляции. Озвучь его тогда.
              Цитата JoeUser @
              Инкапсуляция предполагает объединение данных, ровно и как агрегирование.

              Ничего подобного. Инкапсуляция означает снижения ссылок.
              А агрегирование это техника сокрытия связей в приватных полях и методах.
              Так что противопоставлять их можно. Но по сути то и то является техниками сокрытия информации.

              Что касается что лучше? Я бы в 4 из 5 случаев предпочел бы инкапсуляцию. Потому что агрегирование это все-равно что прятать проблему под ковёр. Вроде не видно но все равно воняет.
                Цитата Pavia @
                ичего подобного. Инкапсуляция означает снижения ссылок.
                А агрегирование это техника сокрытия связей в приватных полях и методах.
                Так что противопоставлять их можно. Но по сути то и то является техниками сокрытия информации.

                Что касается что лучше? Я бы в 4 из 5 случаев предпочел бы инкапсуляцию. Потому что агрегирование это все-равно что прятать проблему под ковёр. Вроде не видно но все равно воняет.

                Это троллинг такой?
                Можно пожалуйста пример агрегирования в приватных методах привести? Я ненароком думал, что агрегирование, как и композиция определяют отношение A has B. А инкапсуляция это типа сокрытие информации.

                Цитата Pavia @
                Потому что агрегирование это все-равно что прятать проблему под ковёр. Вроде не видно но все равно воняет.

                Из этого вывод, что всякие явошарпы с С++сами по сути используют проблемную идиому "прятать под ковер" и все написанное ПО, на этих языках, с использованием классов "воняет"?
                А можно пример, как надо, чтоб не воняло? :huh:
                  :wacko:
                    Инкапсуляция подразумевает объединение данных и методик их обработки в единой неделимой сущности. Сокрытие тут как приятный бонус, способствующий охране инвариантов этой сущности, и которое в общем-то важнее инкапсуляции как таковой. Агрегирование представляет собой рассмотрение готовой сущности как части другой. Несложно представить некую систему, где сокрытие её агрегатов (возможно, только лишь некоторых) нафик не упёрлось и потому к применению не обязательно. Важно, что агрегирование предоставляет лёгкое повторное использование существующего в контексте другой, более ёмкой, задачи.
                    В общем-то я тоже не вполне понимаю, как их сравнивать.

                    Добавлено
                    Не, ну можно, конечно, вспомнить всякое там PImpl и вынести все данные в агрегат. Тогда противопоставить одно другому можно. Но это ведь по-любому будет лишь частный случай использования того и другого. В общем же случае критериев сравнения у них как бы и нет, задачи-то они призваны решать разные.
                      Цитата Qraizer @
                      Агрегирование представляет собой рассмотрение готовой сущности как части другой.

                      Согласно учебнику банды 4.
                      Цитата
                      Агрегирование подразумевает, что один объект владеет другим или несет за него ответственность. В общем случае мы говорим, что объект содержит другой объект или является его
                      частью. Агрегирование означает, что агрегат и его составляющие имеют одинаковое время жизни.

                      А гарантировать такое можно при сокрытие одного класса внутри другого.

                      Цитата Qraizer @
                      Несложно представить некую систему, где сокрытие её агрегатов (возможно, только лишь некоторых) нафик не упёрлось и потому к применению не обязательно.

                      Несложно, очень просто. Но это как раз таки верёвка что-бы выстрелить себе в ногу.

                      Если у вас есть публичная ссылка кто-то захочет её использовать и тогда вы уже не сможете контролировать этот объект. Да конечно разработана теория мягких ссылок и жёстких. Но это всё равно нарушает потокобезапасность.
                              Цитата D_KEY @
                              Ну и было бы неплохо, если бы ты дал определения

                              Цитата OpenGL @
                              +1. У тебя, очевидно, какое-то своё понимание инкапсуляции. Озвучь его тогда.

                              Цитата JoeUser @
                              Инкапсуляция предполагает объединение данных, ровно и как агрегирование.

                              Немного ошибся, но не много! :) Инкапсуляция - это объединение данных и обработчиков (методов), а агрегирование - грубо говоря, помещение "поглощаемого объекта в поглощающий". Во втором случае могут быть и отдельные экземпляры классов, а могут быть и указатели на обработчики (методы и отдельные функции). А вопрос у меня возник на фоне идей Раста, где от наследования отказались, и от инкапсуляции (формально, вынесли в реализацию отдельно).
                                Цитата JoeUser @
                                Немного ошибся, но не много! Инкапсуляция - это объединение данных и обработчиков (методов), а агрегирование - грубо говоря, помещение "поглощаемого объекта в поглощающий". Во втором случае могут быть и отдельные экземпляры классов, а могут быть и указатели на обработчики (методы и отдельные функции). А вопрос у меня возник на фоне идей Раста, где от наследования отказались, и от инкапсуляции (формально, вынесли в реализацию отдельно).

                                Агрегирование это по сути внедрение зависимостей. Инкапсуляция - скрытие деталей реализации под капотом(ну грубо говоря). Это вроде как ортогональные вещи, как их сравнивать :-?
                                Допустим передача параметра в конструктор - агрегация, а реализация интерфейса в классе - инкапсуляция.
                                  Цитата Wound @
                                  Это вроде как ортогональные вещи, как их сравнивать

                                  Да, ошибся таки, согласен. Давай тогда наследование vs агрегирование?
                                    Цитата JoeUser @
                                    Да, ошибся таки, согласен. Давай тогда наследование и агрегирование?

                                    Я когда то книгу читал, Страуструпа вроде, не помню. Вон он там говорил что это все разрешается на семантическом уровне. Т.е. нужно определить вот это будет являтся этим или будет иметь это.

                                    Например ты пишешь класс машина. Машина имеет двигатель, соответственно связь будет выражаться отношением Car has engine, Has A - это у нас либо композиция, либо агрегирование. Агрегирование - это когда двигатель будет передаваться через конструктор. Композиция - это когда двигатель будет создаваться в том же классе, где и объявлен(соответственно уничтожиться вместе с классом). Выбирай любую модель, нужную для твоей системы. Ну в смысле как ты спроектировал и что в твоем случае проще юзать.

                                    Теперь про наследование. Представь что машина у тебя уже есть, а пользователи жалуются, мол де руль тугой. Нужно много сил прикладывать, чтоб повернуть. В итоге тебе нужно выпустить новую машину, но с некоторыми примочками. По сути у тебя это выражается связью A is B, но с примочками.
                                    A is B - это наследование.
                                    Соответственно делаешь класс, наследуешь от нужного, и прикручиваешь ему гидроусилитель руля. Вуаля. Теперь у тебя новая машина, с теми же характеристиками, что и старая, но с гидроусилителем.

                                    В общем я думаю тут холивара не получится. Упрется в то, кто как понимает сущности и какие связи и отношения выстраивает между ними.
                                      Скрытый текст
                                      Киля, спасибо!!! Ты бываешь чрезвычайно полезен, когда вещаешь по тематике :good:
                                        Цитата Qraizer @
                                        Инкапсуляция подразумевает объединение данных и методик их обработки в единой неделимой сущности. Сокрытие тут как приятный бонус, способствующий охране инвариантов этой сущности, и которое в общем-то важнее инкапсуляции как таковой. Агрегирование представляет собой рассмотрение готовой сущности как части другой. Несложно представить некую систему, где сокрытие её агрегатов (возможно, только лишь некоторых) нафик не упёрлось и потому к применению не обязательно. Важно, что агрегирование предоставляет лёгкое повторное использование существующего в контексте другой, более ёмкой, задачи.
                                        В общем-то я тоже не вполне понимаю, как их сравнивать.

                                        Добавлено 16 октября, 21:23
                                        Не, ну можно, конечно, вспомнить всякое там PImpl и вынести все данные в агрегат. Тогда противопоставить одно другому можно. Но это ведь по-любому будет лишь частный случай использования того и другого. В общем же случае критериев сравнения у них как бы и нет, задачи-то они призваны решать разные.

                                        Qraizer, я не знаю на сколько ты знаком с идеологией Rust'а ... Но если как-то интересовался, "ознакамливался", распиши свой взгляд:
                                        1) Почему они (создатели раста) решили не реализовать наследование? Заменили его агрегацией?
                                        2) Почему они (создатели раста) решили инкапсуляцию не реализовывать, а заменили ее типа "иплементацией", считай почти интерфейсами (тут если я не путаю)?
                                          Та откуда ж я знаю. У них спрашивать надо. Когда Страуструпа задолбали подобные вопросы, он аж книжку выпустил с ответами на них. Мож и они сподобятся.
                                          1. Формально – а зачем наследование вообще нужно? Вот просто если разобраться, что в нём хорошего? Сильные связи между предком и всеми его наследниками проводят к тому, что чуть что где в предке дёрнул, и наследники оказываются в опасности из-за зависимостей от него. Толку от наследования чуть: мол, имеем готовый функционал, который лёгким движением руки воспроизводим в новой ипостаси. Ну так это можно и иначе сделать. Если разобраться, наследование нужно только лишь для построения иерархий, ежели вдруг приспичит. Скажем, в языках со статической типизацией это единственный способ удобно и надёжно реализовать полиморфизм.
                                            С другой стороны, наследованию, хорошо зная его механизмы, можно то там, то сям найти адекватное применение. Ну, как бы проще будет именно наследованием, чем другими механизмами. И тогда возникает другой вопрос: что делать с множественным наследованием? Конечно, ты в курсе о том, как об этом отзываются апологеты языков, где его нет. Мол, оно не нужно, у нас есть агрегация вместо этого. Почему-то никто из них не может внятно ответить на встречный вопрос: если вам не нужно множественное наследование, потому что есть агрегация, то почему, коли у вас есть агрегация, вам тем не менее нужно простое наследование? Возможно растовщики ровно так и подумали.
                                          2. Потому что ИМХО инкапсуляция – это сахар. Просто удобно, когда всё в одном месте. На самом деле люди её используются не ради неё, а ради выгод от неё. (Собственно, это справедливо для любой технологии.) Если её можно заменить на что-то иное, дающее те же выгоды, то почему бы и нет. Почему растовщики решили так, как решили, если не "почему бы и нет", то я не знаю.
                                            Цитата Wound @
                                            Теперь про наследование. Представь что машина у тебя уже есть, а пользователи жалуются, мол де руль тугой. Нужно много сил прикладывать, чтоб повернуть. В итоге тебе нужно выпустить новую машину, но с некоторыми примочками. По сути у тебя это выражается связью A is B, но с примочками.
                                            A is B - это наследование.
                                            Соответственно делаешь класс, наследуешь от нужного, и прикручиваешь ему гидроусилитель руля. Вуаля. Теперь у тебя новая машина, с теми же характеристиками, что и старая, но с гидроусилителем.

                                            Наследование так не работает. Потому что вам нужно ещё переписать водителя. Но я не об этом.

                                            Если у нас A1->A2>A3 и вам нужно добавить методы к A3 которые должны получать события от A1 но они там не заложены. Вам нужно будет заменить A1 на B1 и A3 на B3. Поэтому вам нужно всё это протащить через A2. Но что-бы клиенты его не сдохли.

                                            Поэтому проще наследования, реализовать через композицию что в Rust и сделали.
                                            А вот сахар в виде иплементации в руст тут трудно судить.
                                              Скрытый текст
                                              Qraizer,+1!
                                                Цитата JoeUser @
                                                2) Почему они (создатели раста) решили инкапсуляцию не реализовывать, а заменили ее типа "иплементацией", считай почти интерфейсами (тут если я не путаю)?

                                                Зачем эту глупость писать? Оператор точка не является инкапсуляцией как и оператор выбора "|" не является "иплементацией".
                                                  Цитата Pavia @
                                                  Зачем эту глупость писать? Оператор точка не является инкапсуляцией как и оператор выбора "|" не является "иплементацией".

                                                  ниче не понял :blink:
                                                    Цитата Pavia @
                                                    Наследование так не работает. Потому что вам нужно ещё переписать водителя. Но я не об этом.

                                                    А как работает наследование? У вас какое то свое понимание наследования?
                                                    Зачем переписывать водителя? Вы когда садитесь за машину с гидроусилителем руля, переучиваетесь на вождение с гидроусилителем? Т.е. водитель, скажем, ЗИЛ, без гидроусилителя, не сможет сесть и поехать на камазе с гидроусилителем? Что за глупости, не понимаю. :-?

                                                    Цитата Pavia @
                                                    Если у нас A1->A2>A3 и вам нужно добавить методы к A3 которые должны получать события от A1 но они там не заложены. Вам нужно будет заменить A1 на B1 и A3 на B3. Поэтому вам нужно всё это протащить через A2. Но что-бы клиенты его не сдохли.

                                                    :wacko:

                                                    Добавлено
                                                    Цитата Qraizer @
                                                    Почему-то никто из них не может внятно ответить на встречный вопрос: если вам не нужно множественное наследование, потому что есть агрегация, то почему, коли у вас есть агрегация, вам тем не менее нужно простое наследование?

                                                    Чтоб выразить связь A is B. Возьми тот же ГУЙ, как его без наследования нормально писать? Возьми какие нибудь игры, наследованием проще выстраивать иерархии объектов. Ведь проще создать потомка, и вызвать у него нужный метод, чем через объекты вызывать цепочку адского треша.

                                                    Например я создал некий объект, и у меня перед глазами все методы, которые я могу дергать. А с агрегированием как быть?

                                                    Добавлено
                                                    Что до множественного наследования, например в том же C# множественное наследование классов запрещено, для интерфейсов разрешено. И проблема ромба не возникает.
                                                    Сообщение отредактировано: Wound -
                                                      Цитата Wound @
                                                      Возьми тот же ГУЙ, как его без наследования нормально писать?

                                                      Запросто. Непонятно, зачем его с наследованием писать.

                                                      Цитата Wound @
                                                      Ведь проще создать потомка, и вызвать у него нужный метод, чем через объекты вызывать цепочку адского треша.

                                                      А ещё проще глобальную переменную заюзать и дёргать её откуда угодно.

                                                      Цитата Wound @
                                                      Например я создал некий объект, и у меня перед глазами все методы, которые я могу дергать. А с агрегированием как быть?

                                                      Так же. Создать объект и посмотреть глазами все методы, которые ты можешь дёргать.

                                                      Цитата Wound @
                                                      Что до множественного наследования, например в том же C# множественное наследование классов запрещено, для интерфейсов разрешено. И проблема ромба не возникает.

                                                      Сейчас придут плюсовики и объяснят тебе, что проблема ромба — это проблема проектирования, а не множественного наследования. Или как-то так.

                                                      Цитата Qraizer @
                                                      И тогда возникает другой вопрос: что делать с множественным наследованием? Конечно, ты в курсе о том, как об этом отзываются апологеты языков, где его нет. Мол, оно не нужно, у нас есть агрегация вместо этого.

                                                      Отсутствие множественного наследования не обосновывается агрегацией «апологетами языков, где его нет». Ты это выдумал.
                                                        Цитата korvin @
                                                        Запросто. Непонятно, зачем его с наследованием писать.

                                                        Пример можно? Наследование позволяет не дублировать код, и быстро создавать новые элементы управления на основе существующих.

                                                        Цитата korvin @
                                                        А ещё проще глобальную переменную заюзать и дёргать её откуда угодно.

                                                        Глобальную переменную легко переписать нечаяно в каком то другом месте.
                                                        Хотя и их используют там, где они оправданы, синглтон никто не отменял :-?

                                                        Цитата korvin @
                                                        Так же. Создать объект и посмотреть глазами все методы, которые ты можешь дёргать.

                                                        Как? Можно примером?
                                                        Допустим, вот есть у меня класс Checkbox : public Button, у класса checkbox я реализовал функцию отрисовки, все. Теперь у меня есть checkbox, который имеет все те же методы что и кнопка, но выглядит по другому. Как это будет выглядеть с агрегированием? Чтоб у чекбокса были все те же методы?

                                                        Цитата korvin @
                                                        Сейчас придут плюсовики и объяснят тебе, что проблема ромба — это проблема проектирования, а не множественного наследования. Или как-то так.

                                                        Я сам плюсовик, и везде где я видел множественное наследование, оно рано или поздно приводило к ромбовидному, практически неизбежно, особенно, когда система большая.
                                                        Сообщение отредактировано: Wound -
                                                          Цитата Wound @
                                                          Возьми какие нибудь игры, наследованием проще выстраивать иерархии объектов. Ведь проще создать потомка, и вызвать у него нужный метод, чем через объекты вызывать цепочку адского треша.
                                                          НУ так именно это я и сказал. "Проще" ведь не означает "иначе никак".
                                                          Цитата Wound @
                                                          Что до множественного наследования, например в том же C# множественное наследование классов запрещено, для интерфейсов разрешено. И проблема ромба не возникает.
                                                          Вот поэтому и говорят правильнее: множественное наследование реализаций. Интерфейсы не наследуются, они реализуются, поэтому и ромбов нет.
                                                          А что касается проблемы ромбов, то я уже многократно говорил, что её не существует. Опять же, никто, отмечая пресловутую "проблему ромба", не может внятно ответить, как ему быть, если разные интерфейсы, подлежащие реализации в неком классе, окажутся конфликтующими друг с другом. Внезапно "проблема ромба" оказывается не ограничивающейся только реализациями. Если же некто расскажет, что мол в интерфейсах она легко решается, то на просьбу показать, как, приводит ровно те же приёмы, что и при наследовании реализаций.

                                                          Добавлено
                                                          Цитата korvin @
                                                          Сейчас придут плюсовики и объяснят тебе, что проблема ромба — это проблема проектирования, а не множественного наследования. Или как-то так.
                                                          Уже. Только не проблема, а задача.
                                                          Сообщение отредактировано: Qraizer -
                                                            Цитата Qraizer @
                                                            А что касается проблемы ромбов, то я уже многократно говорил, что её не существует.

                                                            Почему? Или в смысле? Просто не совсем понял.

                                                            Цитата Qraizer @
                                                            Опять же, никто, отмечая пресловутую "проблему ромба", не может внятно ответить, как ему быть, если разные интерфейсы, подлежащие реализации в неком классе, окажутся конфликтующими друг с другом.

                                                            Не совсем понял. Реализуются оба интерфейса в одном классе. Т.е. ты реализуешь 2 созвучных метода от разных интерфейсов в классе, который их реализует.
                                                              Цитата korvin @
                                                              Отсутствие множественного наследования не обосновывается агрегацией «апологетами языков, где его нет». Ты это выдумал.
                                                              Я бы с удовольствием это выдумал, но увы, приходится цитировать. На самом деле корень ровно в том, что чаще всего такие дискутируемые стороны сами не разбираются в том, о чём спорят. Точнее, не понимают того, что говорят о разных вещах. И те правы, что множественное наследование реализаций суть нормальная вещь, и те, что утверждают, мол, оно нафик не нужно, ибо агрегация. Решение практически любой подобной дискуссии простое, но крайне для них неочевидное: наследование само по себе маловостребованная вещь, и очень часто, гораздо чаще, чем они себе представляют, может быть заменена на агрегацию. А нередко и должна. И это будет более правильным проектным решением. Причём я сейчас за простое наследование.
                                                              Просто надо осознать, что это разные патерны, служащие разным целям. И друг с другом за области применения не конфликтующие. А все проблемы на стыке их применения возникают от недостаточной грамотности программера, выбирающего то или иное.

                                                              Добавлено
                                                              Цитата Wound @
                                                              Не совсем понял. Реализуются оба интерфейса в одном классе. Т.е. ты реализуешь 2 созвучных метода от разных интерфейсов в классе, который их реализует.
                                                              Тебе на Плюсах?
                                                              ExpandedWrap disabled
                                                                struct ICoolInterface
                                                                {
                                                                  virtual void madeMeCool() = 0;
                                                                };
                                                                 
                                                                struct ICoolerInterface
                                                                {
                                                                  virtual void madeMeCool() = 0;
                                                                };
                                                                 
                                                                struct CCoolImpl: ICoolInterface, ICoolerInterface
                                                                {
                                                                  /* и чё тут писать? */
                                                                };
                                                                Цитата Qraizer @
                                                                Тебе на Плюсах?

                                                                Ну на плюсах как раз таки есть множественное наследование. В C# напишем:
                                                                ExpandedWrap disabled
                                                                  using System;
                                                                   
                                                                  interface Device1
                                                                  {
                                                                      void start();
                                                                  }
                                                                   
                                                                  interface Device2
                                                                  {
                                                                      void start();
                                                                  }
                                                                   
                                                                  public class ConcreteDevice : Device1, Device2
                                                                  {
                                                                      void Device1.start()
                                                                      {
                                                                          Console.WriteLine("Device1 implementation");
                                                                      }
                                                                      
                                                                      void Device2.start()
                                                                      {
                                                                          Console.WriteLine("Device2 implementation");
                                                                      }
                                                                   
                                                                  }
                                                                   
                                                                  public class Test
                                                                  {
                                                                      public static void Main()
                                                                      {
                                                                          Device1 d1 = new ConcreteDevice();
                                                                          Device2 d2 = new ConcreteDevice();
                                                                          
                                                                          d1.start();
                                                                          d2.start();
                                                                      }
                                                                  }

                                                                https://ideone.com/hfL7rP
                                                                  Цитата Qraizer @
                                                                  наследование само по себе маловостребованная вещь, и очень часто, гораздо чаще, чем они себе представляют, может быть заменена на агрегацию. А нередко и должна. И это будет более правильным проектным решением. Причём я сейчас за простое наследование.
                                                                  :yes: :yes: :yes:
                                                                  Причем, по моим наблюдениям, от ООП/Ынтырпрайза головного мозга чаще всего страдают наслаждаются джависты и шарписты. Вот обязательно им все нужно запихнуть в иерархию классов.

                                                                  Добавлено
                                                                  Цитата Wound @
                                                                  Я сам плюсовик, и везде где я видел множественное наследование, оно рано или поздно приводило к ромбовидному, практически неизбежно, особенно, когда система большая.
                                                                  Вот жеж везло тебе. Я никогда не видел проблемы ромба, окромя как на бумаге.
                                                                  Сообщение отредактировано: applegame -
                                                                    Цитата applegame @
                                                                    Вот жеж везло тебе. Я никогда не видел проблемы ромба, окромя как на бумаге.

                                                                    Нигде не встречал конструкций вида:
                                                                    ExpandedWrap disabled
                                                                      class SomeClass : virtual public SomeBase

                                                                    ??
                                                                    Ну так может тебе не доводилось видеть/юзать множественное наследование, окромя как на бумаге, вот и не видел? :-? А я насмотрелся уж на это...
                                                                      Цитата Wound @
                                                                      Ну так может тебе не доводилось видеть/юзать множественное наследование, окромя как на бумаге, вот и не видел?
                                                                      Ну в общем-то почти так и есть. Множественное наследование, кроме как наследование интерфейсов, практически не встречалось, ибо как-то нужды в таких извратах не возникало. Даже простое наследование бывало достаточно редко. Я-то гуи не проектирую, больше серверной хренью занимаюсь.
                                                                      Сообщение отредактировано: applegame -
                                                                        Цитата applegame @
                                                                        Причем, по моим наблюдениям, от ООП/Ынтырпрайза головного мозга чаще всего страдают наслаждаются джависты и шарписты. Вот обязательно им все нужно запихнуть в иерархию классов.

                                                                        Возьми практически любой проект на том же С++, где есть классы, почти везде есть наследование. Так что тут не одни джависты/шарписты этим страдают.
                                                                        Ну и как там в Java хз, шарписты наследуются от интерфейсов в большинстве случаев, а наследование от интерфейсов не приносит тех проблем, о которых тут пытаются рассказать. Тут на сколько я понимаю - про проблемы наследования классов вещают.
                                                                        И я как то слабо представляю как можно, без дублирования кода, эффективно использовать агрегирование. Это же придется дублировать все методы из агрегата, в том классе в котором ты его юзаешь. А если у тебя несколько таких агрегатов, то класс превратиться в длинную портянку кода? :-? Или как?
                                                                          Цитата Wound @
                                                                          Возьми практически любой проект на том же С++, где есть классы, почти везде есть наследование. Так что тут не одни джависты/шарписты этим страдают.
                                                                          Я не говорил, что одни джависты/шарписты этим страдают. И я не про наследование вообще, а про неудержимое желание запихать в иерархию все подряд.
                                                                          Сообщение отредактировано: applegame -
                                                                            Цитата applegame @
                                                                            И я не про наследование вообще, а про неудержимое желание запихать в иерархию все подряд.

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

                                                                            Добавлено
                                                                            Ну и многие технологии/фреймворки завязаны на наследовании, с ними проще работать через наследование.
                                                                              Цитата Wound @
                                                                              Ну не знаю. Мне кажется, что это связано как раз с тем, что если использовать агрегацию, то придется писать просто кучу дублирующихся методов. Просто я пока не понимаю, как это сделать по другому. А это значит классы будут намного сложнее, чем если использовать наследование.
                                                                              Зависит от языка. Например D способен генерить эти методы автоматически на стадии компиляции.
                                                                              Сообщение отредактировано: applegame -
                                                                                Цитата Wound @
                                                                                И я как то слабо представляю как можно, без дублирования кода, эффективно использовать агрегирование. Это же придется дублировать все методы из агрегата, в том классе в котором ты его юзаешь.

                                                                                или просто сделать проперти, которая возвращает интерфейс агрегата.

                                                                                Добавлено
                                                                                Цитата applegame @
                                                                                Зависит от языка. Например D способен генерить эти методы автоматически на стадии компиляции.

                                                                                хммм... заходим на hh.ru и вбиваем "разработчик D"

                                                                                Результат:
                                                                                Цитата
                                                                                Запрос исправлен, по запросу "разработчик D" ничего не найдено


                                                                                Ну нахрен этот D :D
                                                                                  Цитата Fester @
                                                                                  или просто сделать проперти, которая возвращает интерфейс агрегата.

                                                                                  Не, это не просто, это как раз будет костылем и не очень удобным. Т.к. в итоге ты просто запутаешься где и какие методы живут.
                                                                                  Сообщение отредактировано: Wound -
                                                                                    С чего бы это?

                                                                                    ExpandedWrap disabled
                                                                                      interface ICar
                                                                                      {
                                                                                         string Vendor {get;}
                                                                                         string Model {get;}
                                                                                         IEngine Engine { get; }
                                                                                         ...
                                                                                      }
                                                                                       
                                                                                      interface IEngine
                                                                                      {
                                                                                         string Vendor { get; }
                                                                                         int Volume { get; }
                                                                                         ...
                                                                                      }
                                                                                       
                                                                                      class MBS500 : ICar
                                                                                      {
                                                                                         public string Vendor { get {return "Daimler"; } }
                                                                                         public string Model { get { return "Mercedes-Benz S500"; } }
                                                                                         public IEngine Engine {get; private set; }
                                                                                       
                                                                                         public MBS500 (IEngine engine)
                                                                                         {
                                                                                           Engine = engine;
                                                                                         }
                                                                                      }
                                                                                      Цитата Fester @
                                                                                      С чего бы это?

                                                                                      Ты правда веришь, что ответ на этот вопрос получишь? :D
                                                                                        Ну а вдруг? :)
                                                                                          Цитата Fester @
                                                                                          С чего бы это?

                                                                                          1) Интересно, каким боком тут наследование можно засунуть?
                                                                                          2) В любом хеловорде всегда все очевидно.

                                                                                          По твоему этот пример можно переписать как:
                                                                                          ExpandedWrap disabled
                                                                                            class MBS500 : Engine
                                                                                            {
                                                                                             string Vendor { get; }
                                                                                               int Volume { get; }
                                                                                            }

                                                                                          ????

                                                                                          На машинах наверное сложно будет объяснить, но можно попробовать.
                                                                                          Представь что нужно сделать еще одну машину, ровно такую же, как и MBS500, на ее же базе, но называться она будет MBS501, в ней будет все, тоже самое что и в твоей MBS500, но добавляется несколько деталей, которых нет у MBS500, например там люк, кондиционер, пятая или шестая дверь, пулемет там и т.д. Как при такой схеме классов ты это выразишь?
                                                                                          Пример не очень удачный, но после твоего ответа, можно придумать удачный пример. Я просто хочу посмотреть, что ты сделаешь в своем примере.

                                                                                          Цитата OpenGL @
                                                                                          Ты правда веришь, что ответ на этот вопрос получишь?

                                                                                          Странный ты. А где я чего не ответил? Или ты просто как обычно решил трольнуть? Обычно это ты с темы съезжаешь.

                                                                                          Добавлено
                                                                                          Ладно, пока ты думаешь как бы там агрегирование замутить или наследование всунуть, можно привести более удачный пример. Я не знаю работал ты или нет с MFC, но можно взять его за основу и рассмотреть такой пример: https://docs.microsoft.com/en-us/cpp/mfc/re...ss?view=vs-2019
                                                                                          Вот есть у тебя вот такое наследование:
                                                                                          Цитата

                                                                                          Inheritance Hierarchy
                                                                                          CObject

                                                                                          CCmdTarget

                                                                                          CWnd

                                                                                          CListBox

                                                                                          CCheckListBox

                                                                                          Можно сюда добавить еще что то типа:
                                                                                          CCheckListBoxWithTreeState(список чекбоксов с тремя состояниями), который наследуется от CCheckListBox

                                                                                          Попробуй вот в этой иерархии избавиться от наследования и выразить все через агрегирование. Я надеюсь после этого тебе чуточку понятнее станет, что я имел ввиду. Плюс не забывай, что это один из контролов, есть же еще кнопки, фреймы, списки, переключатели и т.д. И их тоже необходимо выразить через агрегирование. Представил? Теперь представь у тебя все это лежит на форме, у каждого класса хренова туча своих внутренних контролов, а методов нет. Все методы будь добр получай через проперти. Это еще к тому, что сами проперти могут пересекаться. Например там GetWindow, GetParentWindow и подобное. ты действительно думаешь, что будет удобнее отдавать наружу только сами классы, а их методы не дублировать?
                                                                                          Ну вот есть у тебя CCheckListBoxWithTreeState, в котором отдельно есть CListBox, отдельно checkbox, отдельно еще там что то. А тебе нужно обработать клик на этом контроле. Какой обработчик из какого проперти надо вызвать? Из CWnd, который спрятан в ListBox, который спрятан в CChecklistBox, который спрятан в CCheckListBoxWithTreeState? CListBox? CCheckListBox? А может быть в каком то другом?

                                                                                          Добавлено
                                                                                          Я вот как то писал класс CCheckListBoxWithTreeState, давно это было, лет 9 назад. Сперва меня посетила мысль, взять написать отдельно чекбокс с тремя состояниями, который наследуется от обычного чекбокса, потом взять ListBox, ну и скрестить это через агрегирование(композицию в моем случае), т.е. получался класс который имеет чекбокс и listbox. Вполне логично, отказ от наследования в пользу агрегирования. Но как то не очень это получилось на практике. Потому что у чекбокса свои события, у листбокса свои, и они начинают конфликтовать друг с другом. Возможно я еще не опытный был, не знал как подружить, но как то не очень получилось у меня в общем. В итоге проще и быстрее и без лишнего гемороя было взять за основу CCheckListBox, отнаследоваться от него, переопределить у него DrawItem, и руками нарисовать там чекбокс, с третьим состоянием, добавить ему обработчики события. И все заработало и наступил мир во всем мире.

                                                                                          Добавлено
                                                                                          Странно что ты Fester читал, читал и даже примера не написал. А я уверен что ты бы написал в рабочем проекте вот такую иерархию:
                                                                                          ExpandedWrap disabled
                                                                                            interface ICar
                                                                                            {
                                                                                               string Vendor {get;}
                                                                                               string Model {get;}
                                                                                               IEngine Engine { get; }
                                                                                               ...
                                                                                            }
                                                                                             
                                                                                            interface IEngine
                                                                                            {
                                                                                               string Vendor { get; }
                                                                                               int Volume { get; }
                                                                                               ...
                                                                                            }
                                                                                             
                                                                                            class MBS500 : ICar
                                                                                            {
                                                                                               public string Vendor { get {return "Daimler"; } }
                                                                                               public string Model { get { return "Mercedes-Benz S500"; } }
                                                                                               public IEngine Engine {get; private set; }
                                                                                             
                                                                                               public MBS500 (IEngine engine)
                                                                                               {
                                                                                                 Engine = engine;
                                                                                               }
                                                                                            }
                                                                                             
                                                                                            public class MBS501 : MBS500
                                                                                            {
                                                                                               public string Model { get { return "Mercedes-Benz S501"; } }
                                                                                             
                                                                                               public MBS501 (IEngine engine)
                                                                                               {
                                                                                                 Engine = engine;
                                                                                               }
                                                                                             
                                                                                               /*тут дополнительные примочки какие то*/
                                                                                            }

                                                                                          Да и тут бы ты ее написал скорее всего - потому что это логично. А речь идет о том, что так делать нельзя, потому что это приводит к ошибкам.
                                                                                          Сообщение отредактировано: Wound -
                                                                                            Цитата Wound @
                                                                                            А где я чего не ответил?

                                                                                            Каюсь, в данном конкретном случае ты вполне нормально на вопрос ответил :yes-sad:
                                                                                              Цитата Wound @
                                                                                              1) Интересно, каким боком тут наследование можно засунуть?
                                                                                              2) В любом хеловорде всегда все очевидно.

                                                                                              Засунуть наследование можно, только вот зачем?


                                                                                              Цитата Wound @
                                                                                              По твоему этот пример можно переписать как:

                                                                                              Если ты хочешь написать как можно больше дублирующего кода, то можно идти в этом направлении. Но зачем?


                                                                                              Цитата Wound @
                                                                                              Представь что нужно сделать еще одну машину, ровно такую же, как и MBS500, на ее же базе, но называться она будет MBS501, в ней будет все, тоже самое что и в твоей MBS500, но добавляется несколько деталей, которых нет у MBS500, например там люк, кондиционер, пятая или шестая дверь и т.д. Как при такой схеме классов ты это выразишь?


                                                                                              ExpandedWrap disabled
                                                                                                interface ICar
                                                                                                {
                                                                                                  string Vendor { get; }
                                                                                                  string Model { get; }
                                                                                                  ICoachwork Coachwork  { get; }
                                                                                                  IEngine Engine { get; }
                                                                                                }
                                                                                                 
                                                                                                interface ICoachwork
                                                                                                {
                                                                                                   IEnumerable<IDoor> Doors {get;}
                                                                                                   ISunroof Sunroof { get; }
                                                                                                }
                                                                                                 
                                                                                                interface ISunroof
                                                                                                {
                                                                                                   bool IsGlas { get; set; }
                                                                                                   bool IsElectric {get; set; }
                                                                                                }
                                                                                                 
                                                                                                class abstract Coachwork : ICoachwork
                                                                                                {
                                                                                                   private List<IDoor> _doors = new List<IDoors>();
                                                                                                   IEnumerable<IDoor> Doors {get  { return _doors; } }
                                                                                                   ISunroof Sunroof { get; private set; }
                                                                                                 
                                                                                                   public Coachwork (ISunroof sunroof)
                                                                                                   {
                                                                                                     Sunroof = sunroof;
                                                                                                   }
                                                                                                 
                                                                                                   protected void AddDoor (IDoor door)
                                                                                                   {
                                                                                                     _doors.Add (door);
                                                                                                   }
                                                                                                }
                                                                                                 
                                                                                                class CoachworkLimusine : Coachwork
                                                                                                {
                                                                                                   public CoachworkLimusine (ISubroof sunroof)
                                                                                                     : base (sunroof)
                                                                                                   {
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new TrunkDoor ());
                                                                                                   }
                                                                                                }
                                                                                                 
                                                                                                 
                                                                                                class CoachworkCombi : Coachwork
                                                                                                {
                                                                                                   public CoachworkCombi (ISubroof sunroof)
                                                                                                     : base (sunroof)
                                                                                                   {
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new Door ());
                                                                                                     AddDoor (new BackDoor ());
                                                                                                   }
                                                                                                }
                                                                                                 
                                                                                                class MBS50x
                                                                                                {
                                                                                                   public string Vendor { get {return "Daimler"; } }
                                                                                                   public string Model { get; private set; }
                                                                                                   public IEngine Engine {get; private set; }
                                                                                                   public ICoachwork Coachwork {get; private set; }
                                                                                                 
                                                                                                   public MBS50x (string model, ICoachwork coachwork, IEngine engine)
                                                                                                   {
                                                                                                     Model = model;
                                                                                                     Coachwork = coachwork;
                                                                                                     Engine = engine;
                                                                                                   }
                                                                                                }


                                                                                              ну и дальше все это компонуется.
                                                                                              например так:
                                                                                              ExpandedWrap disabled
                                                                                                Sunroof sunroof = new Sunroof ();
                                                                                                sunroof.IsGlas = true;
                                                                                                sunroof.IsElectric = true;
                                                                                                 
                                                                                                MBS50x newMB = new MBS50x ("MBS501", new CoachworkCombi(), sunroof);


                                                                                              Добавлено
                                                                                              Цитата Wound @
                                                                                              Странно что ты Fester читал, читал и даже примера не написал. А я уверен что ты бы написал в рабочем проекте вот такую иерархию:

                                                                                              Шеф отвлек звонком :)

                                                                                              Добавлено
                                                                                              Цитата Wound @
                                                                                              Да и тут бы ты ее написал скорее всего - потому что это логично.


                                                                                              Тогда уж так:
                                                                                              ExpandedWrap disabled
                                                                                                class MBS500 : ICar
                                                                                                {
                                                                                                   public string Vendor { get {return "Daimler"; } }
                                                                                                   public string Model { get; private set; }
                                                                                                   public IEngine Engine {get; private set; }
                                                                                                 
                                                                                                   public MBS500 (IEngine engine)
                                                                                                     : this (ingine, "Mercedes-Benz S500")
                                                                                                   {
                                                                                                   }
                                                                                                 
                                                                                                   public MBS500 (IEngine engine, string model)
                                                                                                   {
                                                                                                     Model = model;
                                                                                                     Engine = engine;
                                                                                                   }
                                                                                                }
                                                                                                 
                                                                                                public class MBS501 : MBS500
                                                                                                {
                                                                                                   public MBS501 (IEngine engine)
                                                                                                      : base (engine, "Mercedes-Benz S501")
                                                                                                   {
                                                                                                   }
                                                                                                 
                                                                                                   /*тут дополнительные примочки какие то*/
                                                                                                }


                                                                                              Добавлено
                                                                                              Цитата Wound @
                                                                                              А речь идет о том, что так делать нельзя, потому что это приводит к ошибкам.

                                                                                              Зачем обызательно заменять агрегацию наследованием или наоборот? Для каждой задачи свое решение.
                                                                                                Цитата Fester @
                                                                                                Засунуть наследование можно, только вот зачем?

                                                                                                Вот именно, даже если очень хочется, то смысла от этого вообще нет в твоем примере. Соответственно я и не понял, что ты своим примером хотел показать.

                                                                                                Цитата Fester @
                                                                                                Если ты хочешь написать как можно больше дублирующего кода, то можно идти в этом направлении. Но зачем?

                                                                                                Ну а зачем ты тогда привел этот пример, который ровным счетом ничего не показывает? Я предположил, что ты имел ввиду, что тут можно наследование прикрутить. А зачем же ты еще приводил этот пример?
                                                                                                Тут двигатель даже по смыслу агрегат автомобиля.


                                                                                                Цитата Fester @
                                                                                                ExpandedWrap disabled
                                                                                                  interface ICar
                                                                                                  {
                                                                                                    string Vendor { get; }
                                                                                                    string Model { get; }
                                                                                                    ICoachwork Coachwork  { get; }
                                                                                                    IEngine Engine { get; }
                                                                                                  }
                                                                                                   
                                                                                                  interface ICoachwork
                                                                                                  {
                                                                                                     IEnumerable<IDoor> Doors {get;}
                                                                                                     ISunroof Sunroof { get; }
                                                                                                  }
                                                                                                   
                                                                                                  interface ISunroof
                                                                                                  {
                                                                                                     bool IsGlas { get; set; }
                                                                                                     bool IsElectric {get; set; }
                                                                                                  }
                                                                                                   
                                                                                                  class abstract Coachwork : ICoachwork
                                                                                                  {
                                                                                                     private List<IDoor> _doors = new List<IDoors>();
                                                                                                     IEnumerable<IDoor> Doors {get  { return _doors; } }
                                                                                                     ISunroof Sunroof { get; private set; }
                                                                                                   
                                                                                                     public Coachwork (ISunroof sunroof)
                                                                                                     {
                                                                                                       Sunroof = sunroof;
                                                                                                     }
                                                                                                   
                                                                                                     protected void AddDoor (IDoor door)
                                                                                                     {
                                                                                                       _doors.Add (door);
                                                                                                     }
                                                                                                  }
                                                                                                   
                                                                                                  class CoachworkLimusine : Coachwork
                                                                                                  {
                                                                                                     public CoachworkLimusine (ISubroof sunroof)
                                                                                                       : base (sunroof)
                                                                                                     {
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new TrunkDoor ());
                                                                                                     }
                                                                                                  }
                                                                                                   
                                                                                                   
                                                                                                  class CoachworkCombi : Coachwork
                                                                                                  {
                                                                                                     public CoachworkCombi (ISubroof sunroof)
                                                                                                       : base (sunroof)
                                                                                                     {
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new Door ());
                                                                                                       AddDoor (new BackDoor ());
                                                                                                     }
                                                                                                  }
                                                                                                   
                                                                                                  class MBS50x
                                                                                                  {
                                                                                                     public string Vendor { get {return "Daimler"; } }
                                                                                                     public string Model { get; private set; }
                                                                                                     public IEngine Engine {get; private set; }
                                                                                                     public ICoachwork Coachwork {get; private set; }
                                                                                                   
                                                                                                     public MBS50x (string model, ICoachwork coachwork, IEngine engine)
                                                                                                     {
                                                                                                       Model = model;
                                                                                                       Coachwork = coachwork;
                                                                                                       Engine = engine;
                                                                                                     }
                                                                                                  }

                                                                                                Ну вот видишь, что и требовалось доказать, ты написал примерно так же, как я за тебя выше. Суть не поменялась. В итоге ты сделал ошибку которая тут и обсуждается, юзнув тут наследование. А ошибка заключается в том, чтоб не использовать наследование классов.
                                                                                                По хорошему твой пример должен быть переписан как то вот так:

                                                                                                ExpandedWrap disabled
                                                                                                  interface ICar
                                                                                                  {
                                                                                                     string Vendor {get;}
                                                                                                     string Model {get;}
                                                                                                     IEngine Engine { get; }
                                                                                                     ...
                                                                                                  }
                                                                                                   
                                                                                                  interface IEngine
                                                                                                  {
                                                                                                     string Vendor { get; }
                                                                                                     int Volume { get; }
                                                                                                     ...
                                                                                                  }
                                                                                                   
                                                                                                  class MBS500 : ICar
                                                                                                  {
                                                                                                     public string Vendor { get {return "Daimler"; } }
                                                                                                     public string Model { get { return "Mercedes-Benz S500"; } }
                                                                                                     public IEngine Engine {get; private set; }
                                                                                                   
                                                                                                     public MBS500 (IEngine engine)
                                                                                                     {
                                                                                                       Engine = engine;
                                                                                                     }
                                                                                                  }
                                                                                                   
                                                                                                  interface IModifiedCar: ICar
                                                                                                  {
                                                                                                     void Fire();
                                                                                                  }
                                                                                                   
                                                                                                  public class MBS501 : IModifiedCar
                                                                                                  {
                                                                                                     private MBS500 _modelForUpgrade;
                                                                                                   
                                                                                                     public string Vendor { get {return "Daimler"; } }
                                                                                                     public string Model { get { return "Mercedes-Benz S501"; } }
                                                                                                     public IEngine Engine {get; private set; }
                                                                                                   
                                                                                                     public MBS501(IEngine engine, MBS500 modelForUpgrade)
                                                                                                     {
                                                                                                        _modelForUpgrade = modelForUpgrade;
                                                                                                        Engine = engine;
                                                                                                     }
                                                                                                   
                                                                                                     public string Mashingun {get;set;}
                                                                                                     public string OtherModifications {get;set;}
                                                                                                   
                                                                                                     /*Плюс вот тут ты реализуешь интерфейс ICar, и если какой то метод уже реализован в MBS500 то пишешь примерно такие вот заглушки, предполагается что методы описанные ниже определены в интерфейсе ICar, и реализованы в MBS500*/
                                                                                                     public void Drive()
                                                                                                     {
                                                                                                         _modelForUpgrade.Drive();
                                                                                                     }
                                                                                                   
                                                                                                     public void Run()
                                                                                                     {
                                                                                                          _modelForUpgrade.Run();
                                                                                                     }
                                                                                                   
                                                                                                     public int GetSpeed()
                                                                                                     {
                                                                                                          _modelForUpgrade.GetSpeed();
                                                                                                     }
                                                                                                   
                                                                                                     /*Новый метод Fire из интерфейса IModifiedCar*/
                                                                                                     public void Fire()
                                                                                                     {
                                                                                                        /*тут реализуешь соответствующий функционал*/
                                                                                                     }
                                                                                                  }


                                                                                                Добавлено
                                                                                                Цитата Fester @
                                                                                                Зачем обызательно заменять агрегацию наследованием или наоборот? Для каждой задачи свое решение.

                                                                                                Ну речь зашла о том, что наследование классов - это всегда плохо. Лучше ее избегать всегда и везде, где это возможно. И только если уж совсем приспичит, то можно оставить, и то с нацелом на то, чтоб потом переписать.

                                                                                                Добавлено
                                                                                                А все из за того, что если ты изменишь базовый класс, то можешь сломать потомков, наследование приводит к очень сильной связи объектов, и повлиять на это не возможно никак.
                                                                                                Т.е. по сути наследование классов лучше всегда заменять на паттерн Стратегия.

                                                                                                Добавлено
                                                                                                Но я с этим тоже не согласен. Потому что в конечном итоге придется очень много писать руками дублирующие методы классов, которые при наследовании должны быть базовыми. И очень хорошо это заметно там, где глубокая иерархия типов. например в Гуи. А если у тебя один уровень иерархии объектов, то скорее всего заменить это на агрегирование не составит труда. а если 3-4-5 и больше, то тут уже начинаются неудобства. И проперти твои не помогут, напротив еще больше запутают.
                                                                                                Сообщение отредактировано: Wound -
                                                                                                  Цитата Wound @
                                                                                                  А ошибка заключается в том, чтоб не использовать наследование классов.

                                                                                                  Это ересь какая-то :) ИМХО.

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

                                                                                                  ExpandedWrap disabled
                                                                                                    interface IVehicle
                                                                                                    {
                                                                                                    }
                                                                                                     
                                                                                                    interface IWheelVehicle : IVehicle
                                                                                                    {
                                                                                                    }
                                                                                                     
                                                                                                    interface IFlyingVehicle : IVehicle
                                                                                                    {
                                                                                                    }
                                                                                                     
                                                                                                    interface IMotorVehicle : IWheelVehicle
                                                                                                    {
                                                                                                    }
                                                                                                     
                                                                                                    interface IDiselVehicle : IMotorVehicle
                                                                                                    {
                                                                                                    }
                                                                                                     
                                                                                                    interface IBensinVehicle : IMotorVehicle
                                                                                                    {
                                                                                                    }
                                                                                                     
                                                                                                    interface IElectroVehicle : IMotorVehicle
                                                                                                    {
                                                                                                    }
                                                                                                    Цитата Fester @
                                                                                                    Цитата Wound @
                                                                                                    А ошибка заключается в том, чтоб не использовать наследование классов.

                                                                                                    Это ересь какая-то :) ИМХО.

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

                                                                                                    ExpandedWrap disabled
                                                                                                      interface IVehicle
                                                                                                      {
                                                                                                      }
                                                                                                       
                                                                                                      interface IWheelVehicle : IVehicle
                                                                                                      {
                                                                                                      }
                                                                                                       
                                                                                                      interface IFlyingVehicle : IVehicle
                                                                                                      {
                                                                                                      }
                                                                                                       
                                                                                                      interface IMotorVehicle : IWheelVehicle
                                                                                                      {
                                                                                                      }
                                                                                                       
                                                                                                      interface IDiselVehicle : IMotorVehicle
                                                                                                      {
                                                                                                      }
                                                                                                       
                                                                                                      interface IBensinVehicle : IMotorVehicle
                                                                                                      {
                                                                                                      }
                                                                                                       
                                                                                                      interface IElectroVehicle : IMotorVehicle
                                                                                                      {
                                                                                                      }

                                                                                                    Не, не ересь. Есть серьёзные доводы, которые говорят о том, что наследование плохо. А по поводу твоего примера с интерфейсами, ничего криминального в этом нет, т. к. у тебя там наследование интерфейсов, да и по смыслу наследовать так можно.
                                                                                                      Цитата Wound @
                                                                                                      А по поводу твоего примера с интерфейсами, ничего криминального в этом нет, т. к. у тебя там наследование интерфейсов, да и по смыслу наследовать так можно.

                                                                                                      Делать можно, но получится говно код. Не смотря на то, что это интерфейсы :)

                                                                                                      Плохо впадать в крайности.
                                                                                                        Цитата Fester @
                                                                                                        Делать можно, но получится говно код. Не смотря на то, что это интерфейсы :)

                                                                                                        Плохо впадать в крайности.

                                                                                                        В чем заключается говнокод?
                                                                                                        По поводу наследовани/агрегирования, например: https://metanit.com/sharp/patterns/1.2.php
                                                                                                        Цитата

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


                                                                                                        http://sergeyteplyakov.blogspot.com/2012/12/vs-vs.html
                                                                                                        Цитата

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

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


                                                                                                        https://en.wikipedia.org/wiki/Composition_over_inheritance
                                                                                                          Цитата Wound @
                                                                                                          да и по смыслу наследовать так можно

                                                                                                          Честно говоря - не уверен в логичности этой иерархии. Хотя, могу ошибаться, ибо Джаву не знаю. Но судя, по статье, интерфейсы чем-то напоминают типажи Раста.
                                                                                                          Скрытый текст
                                                                                                          Кстати, OpenGL, в доках по Расту написано, что типажи хоть и похожи на интерфейсы Джавы, но имеют отличия. А какие отличия?

                                                                                                          Интерфейсы определяют поведение. Не пойму зачем в приведенной иерархии связывать "колесо" и "мотор" или "дизель" и "мотор"? У всех транспортных средств есть только одно общее поведение "перемещаться". Те, которые с двигателем - "заправляться", "расходовать топливо". А все остальное, например - способ перемещения, тип топлива, я бы отнес к свойствам уже классов. Я не прав?

                                                                                                          ЗЫ: Да и то, не все, что с двигателем - заправляются, например трамвай.
                                                                                                            Цитата JoeUser @
                                                                                                            Честно говоря - не уверен в логичности этой иерархии. Хотя, могу ошибаться, ибо Джаву не знаю. Но судя, по статье, интерфейсы чем-то напоминают типажи Раста.

                                                                                                            Не знаю что за типажи Раста, но интерфейсы C# это по сути абстрактный базовый класс в С++, у которого все функции чистовиртуальные. Подозреваю что интерфейсы Java, примерно из той же оперы.

                                                                                                            Цитата JoeUser @
                                                                                                            Интерфейсы определяют поведение. Не пойму зачем в приведенной иерархии связывать "колесо" и "мотор" или "дизель" и "мотор"? У всех транспортных средств есть только одно общее поведение "перемещаться". Те, которые с двигателем - "заправляться", "расходовать топливо". А все остальное, например - способ перемещения, тип топлива, я бы отнес к свойствам уже классов. Я не прав?

                                                                                                            В смысле связывать? У машины есть колесо, двигатель, дизель и т.д. Т.е. это все передается извне например через конструктор или еще как то в класс Машина.
                                                                                                            Или ты о какой иерархии говоришь то?

                                                                                                            Добавлено
                                                                                                            Цитата JoeUser @
                                                                                                            ЗЫ: Да и то, не все, что с двигателем - заправляются, например трамвай.

                                                                                                            Ну вот поэтому там будет интерфейс IEngine, от него будут разные реализации - бензиновый, дизель, электрический.
                                                                                                            А класс у тебя принимает интерфейс IEngine, а уж какую реализацию ты подсунешь - такой двигатель у машины и будет.
                                                                                                              Цитата Wound @
                                                                                                              Или ты о какой иерархии говоришь то?

                                                                                                              О иерархии интерфейсов, что была в приведенном кусе кода.
                                                                                                                Цитата JoeUser @
                                                                                                                О иерархии интерфейсов, что была в приведенном кусе кода.

                                                                                                                В каком именно? В том что Fester привел? А блин, я кстати с телефона глядел и увидел почему то только три первых интерфейса, и мне подумалось что там типа:
                                                                                                                ТранспортноеСредство
                                                                                                                КолесноеТранспортноеСредство
                                                                                                                ЛетающееТранспортноеСредство

                                                                                                                И из этого сделал вывод. А щас глянул, там у него целая портянка. Ну да, такое конечно лишено смысла.
                                                                                                                  Цитата Wound @
                                                                                                                  В каком именно? В том что Fester привел?

                                                                                                                  Ага
                                                                                                                    Цитата JoeUser @
                                                                                                                    Ага

                                                                                                                    Я через телефон его сообщение смотрел, у меня код не полностью раскрылся, и я думал речь идет о трех интерфейсах. Типа там ТранспортноеСредство, Летающее и Наземное. И писал исключительно их этих соображений, а щас прочитал твое сообщение про моторы, дизели, отмотал выше и понял что там целая портянка интерфейсов. Такое естественно писать тупо и это говнокод.
                                                                                                                      Цитата Wound @
                                                                                                                      В чем заключается говнокод?

                                                                                                                      Если реализовывать всю эту структуру, то получится много дублируемого кода.

                                                                                                                      Однако, это не значит, что наследование - это плохо.
                                                                                                                      Например, я сейчас пытаюсь пробить шефа на то, чтобы реазизовать примерно такую структуру сообщений
                                                                                                                      ExpandedWrap disabled
                                                                                                                        interface IEvent
                                                                                                                        {
                                                                                                                          IEventType EventType {get;}
                                                                                                                          string Textoverlay {get;}
                                                                                                                          string AlarmMessage {get;}
                                                                                                                          IDatabaseDto DatabaseDto {get;}
                                                                                                                          ну и еще пара пропертей
                                                                                                                        }
                                                                                                                         
                                                                                                                        class ShoeEvent : IEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        class GameEvent : SheEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        class CardDrawEvent : GameEvent
                                                                                                                        {
                                                                                                                          Rank Rank { get; }
                                                                                                                          Suit Suit { get; }
                                                                                                                        ...
                                                                                                                        }
                                                                                                                         
                                                                                                                        class DiscardCardEvent : CardDrawEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        class PlayerCardEvent : CardDrawEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        class BankerCardEvent : CardDrawEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        class GameResultEvent : GameEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        class ShoeErrorEvent : ShoeEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        class ShoeStateEvent : ShoeEvent
                                                                                                                        {
                                                                                                                        }
                                                                                                                         
                                                                                                                        итд



                                                                                                                      Решения при помощи агрегации я тут не вижу. Моя цель в том, чтобы каждый отдельный класс для себя генерировал Textoverlay, AlarmMessage, DatabaseDto и другие общие поля, которые необходимы для обработки сообщения.
                                                                                                                      При этом, GameResultEvent должен быть "наполен" эвентами типа CardDrawEvent и мне надо различать что это был за карта - игрока, банка или на "выбрас".


                                                                                                                      Цитата JoeUser @
                                                                                                                      У всех транспортных средств есть только одно общее поведение "перемещаться". Те, которые с двигателем - "заправляться", "расходовать топливо". А все остальное, например - способ перемещения, тип топлива, я бы отнес к свойствам уже классов. Я не прав?

                                                                                                                      Ты прав, но тольк от части :) Если ты смотришь на транспортное средство, как на средство передвижения, то да - "перемещаться", "заправляться", "расходоваться топливо". Если же смотреть на транспортное средство, как на продукт, которые надо произвести, то "перемещаться", "заправляться", "расходоваться топливо" соввем не важно :) важна конфиругация кузова, надпись с названием и цвет обивки ;)
                                                                                                                      Другое дело, что все это логично было добавлять агрегацией, а не наследованием :)
                                                                                                                        Цитата Fester @
                                                                                                                        Решения при помощи агрегации я тут не вижу. Моя цель в том, чтобы каждый отдельный класс для себя генерировал Textoverlay, AlarmMessage, DatabaseDto и другие общие поля, которые необходимы для обработки сообщения.
                                                                                                                        При этом, GameResultEvent должен быть "наполен" эвентами типа CardDrawEvent и мне надо различать что это был за карта - игрока, банка или на "выбрас".

                                                                                                                        Ну вот везде пишут - что такого, что ты предлагаешь надо избегать. Если будут переделки в базовых класах - то это повлечет кучу проблем. Лично я не люблю делать такие большие иерархии наследования. Слишком запутанно получается, слишком большая связанность классов. На лицо нарушение принципов SOLID.

                                                                                                                        Я не знаю всей специфики твоей задачи, но обычно всякие ивенты решаются с помощью шаблона Посетитель(Visitor) или Наблюдатель(Observer). Возможно тебе нужно пересмотреть дизайн. Слишком много у тебя наследования. ИМХО.

                                                                                                                        Добавлено
                                                                                                                        Цитата Fester @
                                                                                                                        Решения при помощи агрегации я тут не вижу.

                                                                                                                        Так по сути любое наследование можно заменить агрегацией. Просто связь будет не такая тесная, как в случае с наследованием.
                                                                                                                        Сообщение отредактировано: Wound -
                                                                                                                          Цитата Wound @
                                                                                                                          Ну на плюсах как раз таки есть множественное наследование. В C# напишем:
                                                                                                                          ...
                                                                                                                          Хорошо, когда язык поддерживает агрегацию искаропки, да? Вот и ответь теперь, что тебе мешает сделать так же при наследовании реализаций. Гм, ну да... хорошо, когда язык поддерживает множественное наследование реализаций искаропки.

                                                                                                                          Добавлено
                                                                                                                          Цитата applegame @
                                                                                                                          Множественное наследование, кроме как наследование интерфейсов, практически не встречалось, ибо как-то нужды в таких извратах не возникало.
                                                                                                                          Я его юзаю регулярно. Вот только пробелмы ромбов не встречал. Ромбы были, однако. Обычно – при наследовании абстрактных классов сиречь интерфейсов, где оно и должно в общем-то применяться в обязательном порядке.
                                                                                                                          Внимательный читатель, естественно, заметит, что в моём примере интерфейсы наследуются невируально. Ну так это и было сделано намерено, т.к. это разные интерфейсы. Жаль, что никто не обратил на это внимания. Ибо при "правильно оформленном" наследовании от интерфейса компилятор немедленно бы ткнул программера пальцем в конфликт неоднозначности.
                                                                                                                          Беда в том, что заранее далеко не всегда знаешь, разные ли это интерфейсы или следующие версии одного и того же базового. Вот типа как вот так:
                                                                                                                          ExpandedWrap disabled
                                                                                                                            struct IBaseInterface
                                                                                                                            {
                                                                                                                              virtual void madeMeCool() = 0;
                                                                                                                            };
                                                                                                                             
                                                                                                                            struct ICoolInterface  : IBaseInterface { /* тут что-то оригинальное  своё */ }
                                                                                                                            struct ICoolerInterface: IBaseInterface { /* тут что-то совсем другое своё */ }
                                                                                                                             
                                                                                                                            struct CCoolImpl: virtual ICoolInterface, virtual ICoolerInterface
                                                                                                                            {
                                                                                                                              /* всё сделано по правилам, и ничего, как говорится, не предвещало */
                                                                                                                            };
                                                                                                                          Тут хоть ставь virtual, хоть не ставь – всегда найдётся фэйл-сценарий

                                                                                                                          Добавлено
                                                                                                                          Цитата Wound @
                                                                                                                          Ну речь зашла о том, что наследование классов - это всегда плохо.
                                                                                                                          Та ладно тебе. Всегда плохо беспричинная сильная связь между сущностями, а наследование всегда сильно связывает предка с наследниками. Если сильная связь подразумевается, как в лице гуёвых иерархий, например, когда кнопка она же окно, то наследование не привнесёт дополнительного дисбаланса в архитектуру. Переделывай базовый класс окна на здоровье, кнопки автоматом подхватят все модификации, и разве не это ожидается в итоге?
                                                                                                                          Сообщение отредактировано: Qraizer -
                                                                                                                            Цитата Wound @
                                                                                                                            Пример можно?

                                                                                                                            Нет, все ж привыкли строить иерархии наследования. Хотя, HTML, например, близок: только тэги и их атрибуты, никакого наследования.

                                                                                                                            Цитата Wound @
                                                                                                                            Глобальную переменную легко переписать нечаяно в каком то другом месте.

                                                                                                                            Нечаяно можно и метод в базовом классе поменять и поломать всё к чертям.

                                                                                                                            Цитата Wound @
                                                                                                                            Хотя и их используют там, где они оправданы, синглтон никто не отменял

                                                                                                                            Синглтон — антипаттерн уже давно.

                                                                                                                            Цитата Wound @
                                                                                                                            вот есть у меня класс Checkbox : public Button, у класса checkbox я реализовал функцию отрисовки, все. Теперь у меня есть checkbox, который имеет все те же методы что и кнопка, но выглядит по другому.

                                                                                                                            Вот и по рукам тебе за такой класс надавать. CheckBox — это не Button.

                                                                                                                            Цитата Wound @
                                                                                                                            Как это будет выглядеть с агрегированием?

                                                                                                                            CheckBox = Pane { check ; label }

                                                                                                                            Цитата Wound @
                                                                                                                            Чтоб у чекбокса были все те же методы?

                                                                                                                            Какие те же? Зачем CheckBox'у методы Button'а? Ты про click/keypress/etc? Так это не методы Button'а. Ещё раз посмотри на HTML: на любой элемент можно повесить onclick-обработчик, например.

                                                                                                                            Цитата Qraizer @
                                                                                                                            Я бы с удовольствием это выдумал, но увы, приходится цитировать.

                                                                                                                            И кого же ты процитировал?

                                                                                                                            Добавлено
                                                                                                                            Цитата Wound @
                                                                                                                            В чем заключается говнокод?

                                                                                                                            В том что нет ISP.

                                                                                                                            Вместо
                                                                                                                            ExpandedWrap disabled
                                                                                                                              interface Vehicle
                                                                                                                              {
                                                                                                                              }
                                                                                                                               
                                                                                                                              interface WheelVehicle : IVehicle
                                                                                                                              {
                                                                                                                              }
                                                                                                                               
                                                                                                                              interface FlyingVehicle : IVehicle
                                                                                                                              {
                                                                                                                              }

                                                                                                                            Хотя бы
                                                                                                                            ExpandedWrap disabled
                                                                                                                              interface Vehicle
                                                                                                                              {
                                                                                                                              }
                                                                                                                               
                                                                                                                              interface Ground
                                                                                                                              {
                                                                                                                              }
                                                                                                                               
                                                                                                                              interface Flying
                                                                                                                              {
                                                                                                                              }

                                                                                                                            Почувствуй разницу.

                                                                                                                            P.S.
                                                                                                                            Как же раздражает ииотская шарповая нотация
                                                                                                                            ExpandedWrap disabled
                                                                                                                              interface I<name>
                                                                                                                            Сообщение отредактировано: korvin -
                                                                                                                              Цитата korvin @
                                                                                                                              Нет, все ж привыкли строить иерархии наследования. Хотя, HTML, например, близок: только тэги и их атрибуты, никакого наследования.

                                                                                                                              HTML - это язык гипертекстовой разметки, если чего. Как ты его увязал с ЯП, не понимаю.

                                                                                                                              Цитата korvin @
                                                                                                                              Нечаяно можно и метод в базовом классе поменять и поломать всё к чертям.

                                                                                                                              С глобальной переменной это сделать проще.

                                                                                                                              Цитата korvin @
                                                                                                                              Синглтон — антипаттерн уже давно.

                                                                                                                              Незнаю, вот у меня перед глазами лежит книга "Приемы Объектно-Ориентированного проектирования. Паттерны проектирования" за авторством: Э.Гамма, Р.Хелм, Р.Джонсон, Д.Влиссидес.
                                                                                                                              Синглтон описывается на странице 130. Обозначен как паттерн проектирования :-?

                                                                                                                              Цитата korvin @
                                                                                                                              Вот и по рукам тебе за такой класс надавать. CheckBox — это не Button.

                                                                                                                              С чего вдруг? Между прочим, в некоторых фреймворках, чекбоксу можно сделать стиль PressedButton, т.е. меняется только отрисовка - вжатая/отжатая кнопка, либо галочка - есть/нет. В остальном него точно такие же методы как и у кнопки, ну разве что вводятся дополнительные свойства - Checked/Unchecked

                                                                                                                              Цитата korvin @
                                                                                                                              CheckBox = Pane { check ; label }

                                                                                                                              Примитивный пример. Я уже давал на этот счет пояснения тут: Инкапсуляция vs Агрегирование (сообщение #3813134)
                                                                                                                              И если label понятно что это такое, то что такое check - остается только догадываться. Никогда не встречал такого класса :-? Даже в HTML он идет как checkbox

                                                                                                                              Цитата korvin @
                                                                                                                              Какие те же? Зачем CheckBox'у методы Button'а? Ты про click/keypress/etc? Так это не методы Button'а. Ещё раз посмотри на HTML: на любой элемент можно повесить onclick-обработчик, например.

                                                                                                                              Да причем тут HTML то я никак не пойму? Ты сравниваешь разметку с языком программирования.

                                                                                                                              Цитата korvin @
                                                                                                                              В том что нет ISP.

                                                                                                                              Что такое ISP? Я там написал ниже, что не корректно пример понял, так как изначально комментировал его с телефона, а там у меня не все раскрылось.

                                                                                                                              Цитата korvin @
                                                                                                                              Почувствуй разницу.

                                                                                                                              И в чем разница? В других именах? Если сущность одна, и у тебя есть такие же, но более конкретизированные, почему не унаследовать? В любом случае у тебя получится дублирование методов в разных интерфейсах.

                                                                                                                              Добавлено
                                                                                                                              Цитата korvin @
                                                                                                                              Как же раздражает ииотская шарповая нотация

                                                                                                                              А меня бесят маленькие буквы в методах в Java. Придумали какую то хрень, не пойми зачем, и приходится потом с этим извращаться.

                                                                                                                              Добавлено
                                                                                                                              Цитата Qraizer @
                                                                                                                              Хорошо, когда язык поддерживает агрегацию искаропки, да? Вот и ответь теперь, что тебе мешает сделать так же при наследовании реализаций. Гм, ну да... хорошо, когда язык поддерживает множественное наследование реализаций искаропки.

                                                                                                                              Я стараюсь избегать множественного наследования. Уж очень высока вероятность там поиметь проблемы. Не всегда можно что то учесть.

                                                                                                                              Цитата Qraizer @
                                                                                                                              Если сильная связь подразумевается, как в лице гуёвых иерархий, например, когда кнопка она же окно, то наследование не привнесёт дополнительного дисбаланса в архитектуру. Переделывай базовый класс окна на здоровье, кнопки автоматом подхватят все модификации, и разве не это ожидается в итоге?

                                                                                                                              Ну так я не против этого. Просто почитал про это. Народ везде пишет что фигня все это, типа больше проблем, чем пользы. Но лично вот я не понимаю, как тогда ГУИ писать. Вон korvin Знает, у него все просто
                                                                                                                              Берешь и делаешь как в HTML.
                                                                                                                              Сообщение отредактировано: Wound -
                                                                                                                                Цитата Wound @
                                                                                                                                HTML - это язык гипертекстовой разметки, если чего. Как ты его увязал с ЯП, не понимаю.

                                                                                                                                На этом языке разметки уже давно клепают UI. Ну да, +JS для поведения. При чём тут ЯП, когда речь шла о UI, не понятно.

                                                                                                                                Цитата Wound @
                                                                                                                                С глобальной переменной это сделать проще.

                                                                                                                                Конечно. Как и многое другое.

                                                                                                                                Цитата Wound @
                                                                                                                                Незнаю, вот у меня перед глазами лежит книга "Приемы Объектно-Ориентированного проектирования. Паттерны проектирования" за авторством: Э.Гамма, Р.Хелм, Р.Джонсон, Д.Влиссидес.
                                                                                                                                Синглтон описывается на странице 130. Обозначен как паттерн проектирования

                                                                                                                                Библию ещё положи.

                                                                                                                                Тебя не смущает, что книга 1994-го года, а на дворе 2019-й? И что это не Конституция РФ и тем более не учебник по алгебре, например?
                                                                                                                                https://www.michaelsafyan.com/tech/design/patterns/singleton

                                                                                                                                Цитата Wound @
                                                                                                                                Между прочим, в некоторых фреймворках, чекбоксу можно сделать стиль PressedButton, т.е. меняется только отрисовка - вжатая/отжатая кнопка, либо галочка - есть/нет.

                                                                                                                                Обычно это ToggleButton, который к чекбоксам никакого отношения не имеет, кроме как обеспечения такой же смысловой нагрузки: On/Off (Checked/Unchecked, и т.п.) — представления булевого свойства. Ты стиль наследуешь или поведение? Ну да, в этих ваших фреймворках часто представление и семантика слиты в один класс. Каша, да и только. Потом наследуете мух от котлет и наоборот.

                                                                                                                                Цитата Wound @
                                                                                                                                ну разве что вводятся дополнительные свойства - Checked/Unchecked

                                                                                                                                «Дополнительные»? Лол, это и есть вся его смысловая нагрузка, определяющая суть чекбокса как элемента интерфейса.

                                                                                                                                Цитата Wound @
                                                                                                                                то что такое check - остается только догадываться. Никогда не встречал такого класса

                                                                                                                                Это то маленькое окошко, где ставится галочка.

                                                                                                                                Цитата Wound @
                                                                                                                                Даже в HTML он идет как checkbox

                                                                                                                                Потому что там checkbox — готовый примитив, который, кстати, не наследуется от button.

                                                                                                                                Цитата Wound @
                                                                                                                                Да причем тут HTML то я никак не пойму? Ты сравниваешь разметку с языком программирования.

                                                                                                                                При чём тут язык программирования? Мы о UI фреймворках/тулкитах говорим. HTML+CSS+JS — это UI-тулкит.

                                                                                                                                Цитата Wound @
                                                                                                                                Что такое ISP?

                                                                                                                                Interface Segregation Principle.

                                                                                                                                Цитата Wound @
                                                                                                                                И в чем разница? В других именах? Если сущность одна, и у тебя есть такие же, но более конкретизированные, почему не унаследовать?

                                                                                                                                :facepalm:

                                                                                                                                Flying может быть не только Vehicle. Ты внимательней прочитай.

                                                                                                                                Цитата Wound @
                                                                                                                                А меня бесят маленькие буквы в методах в Java. Придумали какую то хрень, не пойми зачем, и приходится потом с этим извращаться.

                                                                                                                                А маленькие буквы в именах полей в C# тебя не бесят? Нахера вы захламляете имена идиотскими префиксами? У классов префикс C пишете? А у абстарктных классов — AC? А если публичный, нужно P добавлять? А S к sealed?
                                                                                                                                  Цитата Qraizer @
                                                                                                                                  Тут хоть ставь virtual, хоть не ставь – всегда найдётся фэйл-сценарий

                                                                                                                                  Написал незафэйленный сценарий:

                                                                                                                                  ExpandedWrap disabled
                                                                                                                                    #include <iostream>
                                                                                                                                    using namespace std;
                                                                                                                                     
                                                                                                                                    struct IBaseInterface {
                                                                                                                                      virtual void madeMeCool() = 0;
                                                                                                                                    };
                                                                                                                                        
                                                                                                                                    struct ICoolInterface : IBaseInterface {
                                                                                                                                      /* тут что-то оригинальное  своё */
                                                                                                                                      virtual void madeMeCool() override {
                                                                                                                                        cout << "ICoolInterface сделал cool\n";
                                                                                                                                      }
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                    struct ICoolerInterface: IBaseInterface {
                                                                                                                                      /* тут что-то совсем другое своё */
                                                                                                                                      virtual void madeMeCool() override {
                                                                                                                                        cout << "ICoolerInterface тоже сделал cool\n";
                                                                                                                                      }
                                                                                                                                    };
                                                                                                                                        
                                                                                                                                    struct CCoolImpl: virtual ICoolInterface, virtual ICoolerInterface {
                                                                                                                                      /* всё сделано по правилам, и ничего, как говорится, не предвещало */
                                                                                                                                      virtual void madeMeCool() override {
                                                                                                                                        ICoolInterface::madeMeCool();
                                                                                                                                        ICoolerInterface::madeMeCool();
                                                                                                                                        cout << "CCoolImpl сделал cool вдогоночку\n";
                                                                                                                                      }
                                                                                                                                    };
                                                                                                                                     
                                                                                                                                    int main() {
                                                                                                                                      CCoolImpl cool;
                                                                                                                                      cool.madeMeCool();
                                                                                                                                      return 0;
                                                                                                                                    }

                                                                                                                                  И как его зафэйлить? Приведи пример, плс.
                                                                                                                                    Скрытый текст
                                                                                                                                    Цитата korvin @
                                                                                                                                    Как же раздражает ииотская шарповая нотация

                                                                                                                                    Она как минимум дельфийская :)
                                                                                                                                    Сообщение отредактировано: OpenGL -
                                                                                                                                      Цитата korvin @
                                                                                                                                      На этом языке разметки уже давно клепают UI. Ну да, +JS для поведения. При чём тут ЯП, когда речь шла о UI, не понятно.

                                                                                                                                      Не только на этом языке разметки клепают UI, это во первых. Потому как в практически любой ОС, есть окна/диалоги и т.п. которые работают не через HTML, а ты говоришь судя по всему исключительно про Web, только причем он тут?

                                                                                                                                      Цитата korvin @
                                                                                                                                      Тебя не смущает, что книга 1994-го года, а на дворе 2019-й? И что это не Конституция РФ и тем более не учебник по алгебре, например?
                                                                                                                                      https://www.michaelsafyan.com/tech/design/patterns/singleton

                                                                                                                                      Нет не смущает :-? Может быть и SOLID тогда устарел и его нужно в топку выкинуть? А то ему тоже уже под 20 лет. :)

                                                                                                                                      Цитата korvin @
                                                                                                                                      Обычно это ToggleButton, который к чекбоксам никакого отношения не имеет, кроме как обеспечения такой же смысловой нагрузки: On/Off (Checked/Unchecked, и т.п.) — представления булевого свойства. Ты стиль наследуешь или поведение? Ну да, в этих ваших фреймворках часто представление и семантика слиты в один класс. Каша, да и только. Потом наследуете мух от котлет и наоборот.

                                                                                                                                      Ну давай посмотрим как это в HTML описывается: https://www.w3schools.com/tags/att_input_type_checkbox.asp
                                                                                                                                      ExpandedWrap disabled
                                                                                                                                        HTML <input type="checkbox">

                                                                                                                                      input?
                                                                                                                                      А чего не checkbox ?

                                                                                                                                      Цитата korvin @
                                                                                                                                      «Дополнительные»? Лол, это и есть вся его смысловая нагрузка, определяющая суть чекбокса как элемента интерфейса.

                                                                                                                                      Я с тобой не соглашусь, потому как помимо Checked/Unchecked - ему хорошо бы иметь все те же методы, что имеет кнопка. Нажать/Отпустить/Отрисовка/MouseMove и т.д. Зачем писать повторно все тоже самое, что ты будешь писать для кнопки какой нибудь? Дублирование кода на лицо получается.

                                                                                                                                      Цитата korvin @
                                                                                                                                      При чём тут язык программирования? Мы о UI фреймворках/тулкитах говорим. HTML+CSS+JS — это UI-тулкит.

                                                                                                                                      Причем тут HTML+CSS+JS, мы о Веб не говорим(я так точно о нем не говорил), а ты приводишь Веб. Зачем рассматривать Веб, если речь идет о ГУИ фреймворках языков программирования?


                                                                                                                                      Цитата korvin @
                                                                                                                                      Interface Segregation Principle.

                                                                                                                                      Если ты имел ввиду те 10 интерфейсов, то я уже писал что там херня написана. А если ты имеешь ввиду три первых - то в каком месте там что нарушается? Этот принцип нарушится тогда, когда у тебя классы будут вынуждены реализовывать методы интерфейсов, который реализовывать не должны. А если ты самые общие методы вынесешь в базовый интерфейс, а те два дополнишь своими, то этот принцип нарушаться не будет.

                                                                                                                                      Цитата korvin @
                                                                                                                                      Flying может быть не только Vehicle. Ты внимательней прочитай.

                                                                                                                                      В реальной жизни? Очень может быть. Но обычно проектируют согласно ТЗ. Если ты пишешь какую то программу для управления исключительно транспортными средствами, то например птиц - можно не учитывать.

                                                                                                                                      Цитата korvin @
                                                                                                                                      А маленькие буквы в именах полей в C# тебя не бесят?

                                                                                                                                      Это как тут что ле: http://hg.openjdk.java.net/jdk8/jdk8/jdk/f.../ArrayList.java ?
                                                                                                                                      ExpandedWrap disabled
                                                                                                                                           private static final long serialVersionUID = 8683452581122892189L;
                                                                                                                                         
                                                                                                                                            ...
                                                                                                                                         
                                                                                                                                            /**
                                                                                                                                             * The size of the ArrayList (the number of elements it contains).
                                                                                                                                             *
                                                                                                                                             * @serial
                                                                                                                                             */
                                                                                                                                            private int size;


                                                                                                                                      Цитата korvin @
                                                                                                                                      Нахера вы захламляете имена идиотскими префиксами? У классов префикс C пишете?

                                                                                                                                      По поводу префиксов - необязательно так делать. Я думаю так делают в основном С++сники, я вот не помню какую книгу по шарпам читал, так там автор говорил что поля могут совпадать с входными значениями, и никакого криминала в этом нет, более того, даже принято вызывать поля через this. Ну что то типа там:

                                                                                                                                      ExpandedWrap disabled
                                                                                                                                        public class SomeClass
                                                                                                                                        {
                                                                                                                                           private int speed;
                                                                                                                                           SomeClass(int speed)
                                                                                                                                           {
                                                                                                                                              this.speed = speed;
                                                                                                                                           }
                                                                                                                                        }

                                                                                                                                      На сколько я знаю С++сники не любят писать this, поэтому видимо придумали название полей с подчеркивания писать. Ну типа чтоб не писать длинный this. и при этом чтоб было понятно что это поле класса, а не какая то левая переменная в методе или из параметров. По поводу префикса C у класса - это тоже дело рук С++сников, ЕМНИП, а пошло это еще из классов MFC, и венгерской нотации.

                                                                                                                                      Цитата korvin @
                                                                                                                                      А у абстарктных классов — AC? А если публичный, нужно P добавлять? А S к sealed?

                                                                                                                                      Ну это ты уже сам придумал.
                                                                                                                                        Цитата Wound @
                                                                                                                                        Ну вот везде пишут - что такого, что ты предлагаешь надо избегать. Если будут переделки в базовых класах - то это повлечет кучу проблем. Лично я не люблю делать такие большие иерархии наследования. Слишком запутанно получается, слишком большая связанность классов. На лицо нарушение принципов SOLID.

                                                                                                                                        Ну вот возьмем цепочку классов:
                                                                                                                                        ExpandedWrap disabled
                                                                                                                                          interface IEvent
                                                                                                                                          {
                                                                                                                                            IEventType EventType {get;}
                                                                                                                                            string Textoverlay {get;}
                                                                                                                                            string AlarmMessage {get;}
                                                                                                                                            IDatabaseDto DatabaseDto {get;}
                                                                                                                                            ну и еще пара пропертей
                                                                                                                                          }
                                                                                                                                           
                                                                                                                                          class abstract ShoeEvent : IEvent
                                                                                                                                          {
                                                                                                                                          }
                                                                                                                                           
                                                                                                                                          class abstract GameEvent : ShoeEvent
                                                                                                                                          {
                                                                                                                                          }
                                                                                                                                           
                                                                                                                                          class abstract CardDrawEvent : GameEvent
                                                                                                                                          {
                                                                                                                                            Rank Rank { get; }
                                                                                                                                            Suit Suit { get; }
                                                                                                                                          ...
                                                                                                                                           
                                                                                                                                            string Textoverlay {get { реализация } }
                                                                                                                                            string AlarmMessage {get { реализация } }
                                                                                                                                            IDatabaseDto DatabaseDto {get { реализация } }
                                                                                                                                          }
                                                                                                                                           
                                                                                                                                          class DiscardCardEvent : CardDrawEvent
                                                                                                                                          {
                                                                                                                                          }
                                                                                                                                           
                                                                                                                                          class PlayerCardEvent : CardDrawEvent
                                                                                                                                          {
                                                                                                                                          }
                                                                                                                                           
                                                                                                                                          class BankerCardEvent : CardDrawEvent
                                                                                                                                          {
                                                                                                                                          }

                                                                                                                                        как тут можно заменить наследование агрегацией?
                                                                                                                                        Ну в данном примере (в том виде, как показано тут) ShoeEvent и GameEvent можно заменить интерфейсами. А вместо DiscardCardEvent, PlayerCardEvent и BankerCardEvent можно сделать enum. Но ведь это не агрегация :)


                                                                                                                                        Цитата Wound @
                                                                                                                                        Я не знаю всей специфики твоей задачи, но обычно всякие ивенты решаются с помощью шаблона Посетитель(Visitor) или Наблюдатель(Observer). Возможно тебе нужно пересмотреть дизайн. Слишком много у тебя наследования. ИМХО.

                                                                                                                                        Пересмотреть дизайн - это написать все с нуля :) Тут коду больше 10 лет и сейчас сделан один класс, который отвечает за все. Недостатком такой структуры является то, что Textoverlay, AlarmMessage и DatabaseDto живут "вне" эвента в результате для обработки всего этого добра пишется куча ненужного кода.
                                                                                                                                        Сообщение отредактировано: Fester -
                                                                                                                                          Цитата Fester @
                                                                                                                                          как тут можно заменить наследование агрегацией?
                                                                                                                                          Ну в данном примере (в том виде, как показано тут) ShoeEvent и GameEvent можно заменить интерфейсами. А вместо DiscardCardEvent, PlayerCardEvent и BankerCardEvent можно сделать enum. Но ведь это не агрегация

                                                                                                                                          Очень просто, то от чего ты наследуешься - делаешь полем класса + в конструктор параметр прокидываешь. Я не знаю специфики твоей задачи, но у тебя слишком много наследования в твоей иерархии классов. Может быть проще какой нибудь Visitor прикрутить или Наблюдатель там? Почему ты не хочешь пресмотреть свою задачу и юзнуть шаблоны проектирования, вместо бездумного наследования. У тебя потом по ходу работы, всплывет какая то хрень, и будешь ты костыли лепить к этой иерархии, и писать еще больше наследования.

                                                                                                                                          Цитата Fester @
                                                                                                                                          Пересмотреть дизайн - это написать все с нуля Тут коду больше 10 лет и сейчас сделан один класс, который отвечает за все. Недостатком такой структуры является то, что Textoverlay, AlarmMessage и DatabaseDto живут "вне" эвента в результате для обработки всего этого добра пишется куча ненужного кода.

                                                                                                                                          Ну вот видишь - вот и вылезла проблема. Рефакторингу не подлежит, т.к. вот такое наследование в него заложено. А была бы агрегация, то отрефакторилось бы легко.
                                                                                                                                            Цитата Fester @
                                                                                                                                            хммм... заходим на hh.ru и вбиваем "разработчик D"
                                                                                                                                            Ну нахрен этот D
                                                                                                                                            И какое это имеет отношение к обсуждаемой теме? И D не уникален в этом плане. Ruby и PHP тоже умеют обрабатывать вызовы несуществующих методов и при желании можно проксировать их в агрегируемый объект.
                                                                                                                                            Цитата Wound @
                                                                                                                                            Ну речь зашла о том, что наследование классов - это всегда плохо. Лучше ее избегать всегда и везде, где это возможно. И только если уж совсем приспичит, то можно оставить, и то с нацелом на то, чтоб потом переписать.
                                                                                                                                            Ну, по крайней мере на этом форуме, полагаю, никто так не считает.
                                                                                                                                            Цитата Wound @
                                                                                                                                            По поводу префиксов - необязательно так делать. Я думаю так делают в основном С++сники,
                                                                                                                                            Нет, классические C++сники так не делают. Посмотри boost и стандартную либу - никаких префиксов.
                                                                                                                                            Префиксы это другая болезнь - Microsoft Головного Мозга.
                                                                                                                                            Сообщение отредактировано: applegame -
                                                                                                                                              Цитата Wound @
                                                                                                                                              Очень просто, то от чего ты наследуешься - делаешь полем класса + в конструктор параметр прокидываешь.

                                                                                                                                              Но рано или поздно мне надо будет отправить, скажем, Textoverlay. Т.е. конечный класс должен имплементировать этот интерфейс чтобы я "разматывать" цепочку агрегаций.


                                                                                                                                              Цитата Wound @
                                                                                                                                              Может быть проще какой нибудь Visitor прикрутить или Наблюдатель там?

                                                                                                                                              Может и проще, но для этого надо все переписать. Сейчас сделано в лоб - пришел евент -> добавили эвент в игру -> проверили нарушаются ли правила (их штук 10), если нарушаются, то создали соответствующий эвент -> отправили все (начальные и созданные) на отправку в подсистемы (сохранение в БД, отправка Textoverlay, сообщение о нарушениях итд). Т.е. наверное это ближе к наблюдателю, но переделывать существующий код никто не даст.


                                                                                                                                              Цитата Wound @
                                                                                                                                              Ну вот видишь - вот и вылезла проблема. Рефакторингу не подлежит, т.к. вот такое наследование в него заложено. А была бы агрегация, то отрефакторилось бы легко.

                                                                                                                                              Рефакторингу не подлежит, т.к. там сейчас вообще нет никакого дизайна :) Все делается в лоб. Грубо говоря, есть класс, который отвечает за отправку данных на все подсистемы. Так вот в этом классе есть поле Textoverlay, которое заполняется по мере обработки сообщения, потом, когда вызывается вункция "отправить все на подсистемы", берется поле Textoverlay и отправляется куда надо и сколько надо раз. После чего содерживое поля обнуляется :)
                                                                                                                                                Цитата Fester @
                                                                                                                                                Но рано или поздно мне надо будет отправить, скажем, Textoverlay. Т.е. конечный класс должен имплементировать этот интерфейс чтобы я "разматывать" цепочку агрегаций.

                                                                                                                                                Ну так и в чем проблема, не пойму?
                                                                                                                                                У тебя все классы, которые друг от друга наследуются, теперь будут наследоваться от IEvent, и плюс еще от какого то, если тебе расширить функционал нужно.
                                                                                                                                                А передавать в них через конструктор ты будешь то, от чего сейчас наследуешься.
                                                                                                                                                В итоге все классы у тебя имплементируют твой интерфейс.


                                                                                                                                                Цитата Fester @
                                                                                                                                                Может и проще, но для этого надо все переписать. Сейчас сделано в лоб - пришел евент -> добавили эвент в игру -> проверили нарушаются ли правила (их штук 10), если нарушаются, то создали соответствующий эвент -> отправили все (начальные и созданные) на отправку в подсистемы (сохранение в БД, отправка Textoverlay, сообщение о нарушениях итд). Т.е. наверное это ближе к наблюдателю, но переделывать существующий код никто не даст.

                                                                                                                                                Ну тут можно только посочувствовать. :-?
                                                                                                                                                  Цитата Fester @
                                                                                                                                                  важна конфиругация кузова, надпись с названием и цвет обивки ;)

                                                                                                                                                  Никаких противоречий! Интерфейсы определяют "поведение" (или "способность поведения"), а праперти - "состояние".
                                                                                                                                                  Цвет - это состояние. Конкретная конфигурация - это состояние.

                                                                                                                                                  Цитата Fester @
                                                                                                                                                  Другое дело, что все это логично было добавлять агрегацией, а не наследованием

                                                                                                                                                  Вот тут я полностью согласен с Килей, он как-то пару листов назад расписал условия, когда нужно руководствоваться здравым смыслом и опираться на отношения "является" или "имеет". По факту:

                                                                                                                                                  1) Наследование используется, если имеем отношение "является"
                                                                                                                                                  2) Агрегация или композиция используются, если имеем отношение "имеет"

                                                                                                                                                  При агрегации что-то конструируем во-вне класса и сконструированное передаем в виде параметра конструктору.
                                                                                                                                                  При композиции конструируем нужное с самом классе.

                                                                                                                                                  Ну как-то так вроде, если я все правильно понял.
                                                                                                                                                    Цитата JoeUser @
                                                                                                                                                    Вот тут я полностью согласен с Килей, он как-то пару листов назад расписал условия, когда нужно руководствоваться здравым смыслом и опираться на отношения "является" или "имеет". По факту:

                                                                                                                                                    1) Наследование используется, если имеем отношение "является"
                                                                                                                                                    2) Агрегация или композиция используются, если имеем отношение "имеет"

                                                                                                                                                    При агрегации что-то конструируем во-вне класса и сконструированное передаем в виде параметра конструктору.
                                                                                                                                                    При композиции конструируем нужное с самом классе.

                                                                                                                                                    Ну как-то так вроде, если я все правильно понял.

                                                                                                                                                    Ну тут еще есть всякие оговорки, типа если у тебя отношение "является", но при этом дочерний класс замещает методы базового, или вообще не использует их, то такое наследование - плохое, ибо чревато проблемами. И тут надо уже вводить агрегирование, либо пересматривать дизайн.
                                                                                                                                                    В идеале наследование подходит там, где у тебя отношения "is a" плюс ко всему дочерний класс будет исключительно добавлять новую функциональность и вообще не будет замещать методы базового класса.
                                                                                                                                                    Называется это вроде Принцип подстановки Барбары Лисков
                                                                                                                                                    Сообщение отредактировано: Wound -
                                                                                                                                                      Цитата Fester @
                                                                                                                                                      Грубо говоря, есть класс, который отвечает за отправку данных на все подсистемы. Так вот в этом классе есть поле Textoverlay, которое заполняется по мере обработки сообщения, потом, когда вызывается вункция "отправить все на подсистемы", берется поле Textoverlay и отправляется куда надо и сколько надо раз. После чего содерживое поля обнуляется

                                                                                                                                                      :blink: :blink: :blink:
                                                                                                                                                        Цитата Wound @
                                                                                                                                                        Ну тут еще есть всякие оговорки

                                                                                                                                                        Согласен. Как раз вчера с чьей-то подачи про SOLID читал.
                                                                                                                                                          Цитата Wound @
                                                                                                                                                          У тебя все классы, которые друг от друга наследуются, теперь будут наследоваться от IEvent

                                                                                                                                                          Это приведет к избыточности ;)
                                                                                                                                                            Цитата Fester @
                                                                                                                                                            Это приведет к избыточности

                                                                                                                                                            В смысле? К какой избыточности? Они и так у тебя по факту все наследуются от одного интерфейса.
                                                                                                                                                              Цитата JoeUser @
                                                                                                                                                              1) Наследование используется, если имеем отношение "является"
                                                                                                                                                              Не всегда. Известная проблема Круга-Эллипса. Когда Круг является Эллипсом, но наследовать Круг от Эллипса - очень плохая идея.
                                                                                                                                                                Цитата Wound @

                                                                                                                                                                В смысле? К какой избыточности?


                                                                                                                                                                Если я правильно тебя понял, то ты предлагаешь что-то вроде такого:
                                                                                                                                                                ExpandedWrap disabled
                                                                                                                                                                  interface IEvent
                                                                                                                                                                  {
                                                                                                                                                                    string Textoverlay {get;}
                                                                                                                                                                  }
                                                                                                                                                                   
                                                                                                                                                                  class ShoeEvent : IEvent
                                                                                                                                                                  {
                                                                                                                                                                    public string Textoverlay {get; }
                                                                                                                                                                  }
                                                                                                                                                                   
                                                                                                                                                                  class GameEvent : IEvent
                                                                                                                                                                  {
                                                                                                                                                                    public GameEvent (ShoeEvent shoeEvent)
                                                                                                                                                                    {
                                                                                                                                                                       ShoeEvent = shoeEvent;
                                                                                                                                                                    }
                                                                                                                                                                    public ShoeEvent ShoeEvent {get; private set; }
                                                                                                                                                                    public string Textoverlay {get; }
                                                                                                                                                                  }
                                                                                                                                                                   
                                                                                                                                                                  class CardDrawEvent : IEvent
                                                                                                                                                                  {
                                                                                                                                                                    public CardDrawEvent (GameEvent gameEvent)
                                                                                                                                                                    {
                                                                                                                                                                       GameEvent= gameEvent;
                                                                                                                                                                    }
                                                                                                                                                                    public GameEvent GameEvent{get; private set; }
                                                                                                                                                                    public string Textoverlay {get; }
                                                                                                                                                                  }
                                                                                                                                                                   
                                                                                                                                                                  class DiscardCardEvent : IEvent
                                                                                                                                                                  {
                                                                                                                                                                    public DiscardCardEvent (CardDrawEvent cardDrawEvent)
                                                                                                                                                                    {
                                                                                                                                                                       CardDrawEvent = cardDrawEvent;
                                                                                                                                                                    }
                                                                                                                                                                    public CardDrawEvent CardDrawEvent {get; private set; }
                                                                                                                                                                    public string Textoverlay {get; }
                                                                                                                                                                  }


                                                                                                                                                                Совершенно очевидно, что тут избыточный код (имплементация Textoverlay мне нужна только DiscardCardEvent) и вообще я задолбался все это копипастить. И я не говорю о том, что при такой конструкции есть возможность создавать объекты промежуточных типов, а мне этого не надо (в моем примере они абстрактные)
                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                  Не всегда. Известная проблема Круга-Эллипса. Когда Круг является Эллипсом, но наследовать Круг от Эллипса - очень плохая идея.

                                                                                                                                                                  Есть еще более классическая фигня - лопата копает яму, или яма копается лопатой? :D
                                                                                                                                                                    Цитата Fester @
                                                                                                                                                                    Совершенно очевидно, что тут избыточный код (имплементация Textoverlay мне нужна только DiscardCardEvent) и вообще я задолбался все это копипастить. И я не говорю о том, что при такой конструкции есть возможность создавать объекты промежуточных типов, а мне этого не надо (в моем примере они абстрактные)

                                                                                                                                                                    Ну вот, видишь. Ты сам пришел к тому, что пытался опровергнуть, а именно:
                                                                                                                                                                    Цитата Fester @
                                                                                                                                                                    Цитата Wound
                                                                                                                                                                    И я как то слабо представляю как можно, без дублирования кода, эффективно использовать агрегирование. Это же придется дублировать все методы из агрегата, в том классе в котором ты его юзаешь.

                                                                                                                                                                    или просто сделать проперти, которая возвращает интерфейс агрегата.

                                                                                                                                                                    Вот теперь ты точно понял, о чем идет речь. Ну или можешь взять свой совет на заметку :D

                                                                                                                                                                    Добавлено
                                                                                                                                                                    Если верить applegame'у, то в D - не придется копипастить все руками, язык поддерживает это из каробки. Соответственно в таком языке можно вообще уходить смело от наследования.
                                                                                                                                                                    Сообщение отредактировано: Wound -
                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                      Вот теперь ты точно понял, о чем идет речь. Ну или можешь взять свой совет на заметку

                                                                                                                                                                      ну так в приведенном мной примере я сразу говорил, что не вижу разумного способа заменить наследование агрегацией.
                                                                                                                                                                      Более того, тут показано, что в общем случае наследование нельзя заменить агрегацией. Это два разных инструмента и предназначены они для разных целей.

                                                                                                                                                                      Добавлено
                                                                                                                                                                      Цитата Wound @
                                                                                                                                                                      Если верить applegame'у, то в D - не придется копипастить все руками, язык поддерживает это из каробки. Соответственно в таком языке можно вообще уходить смело от наследования.

                                                                                                                                                                      Это ради бога, вот только есть верить hh.ru, то этот D нахрен никому не нужен, а значит нет смыла тратить на него свое время :)
                                                                                                                                                                        Цитата Fester @
                                                                                                                                                                        ну так в приведенном мной примере я сразу говорил, что не вижу разумного способа заменить наследование агрегацией.

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

                                                                                                                                                                        Цитата Fester @
                                                                                                                                                                        Более того, тут показано, что в общем случае наследование нельзя заменить агрегацией. Это два разных инструмента и предназначены они для разных целей.

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

                                                                                                                                                                        Добавлено
                                                                                                                                                                        Цитата Fester @
                                                                                                                                                                        Это ради бога, вот только есть верить hh.ru, то этот D нахрен никому не нужен, а значит нет смыла тратить на него свое время

                                                                                                                                                                        Ну ради справедливости, стоит заметить что я встречал вакансии на D, но никак основные, а как сопутствующие. Т.е. там Ищеться программист C# с знанием D, например.
                                                                                                                                                                          Небось это контора applegame и искала спецов :)
                                                                                                                                                                            Цитата OpenGL @
                                                                                                                                                                            Небось это контора applegame и искала спецов

                                                                                                                                                                            :-?
                                                                                                                                                                              Цитата Астарот @
                                                                                                                                                                              Есть еще более классическая фигня - лопата копает яму, или яма копается лопатой?
                                                                                                                                                                              Ну это камень в другой огород. Не в огород наследования. :)
                                                                                                                                                                              Цитата Wound @
                                                                                                                                                                              Если верить applegame'у, то в D - не придется копипастить все руками, язык поддерживает это из каробки. Соответственно в таком языке можно вообще уходить смело от наследования.
                                                                                                                                                                              Нет, динамический полиморфизм в D только через наследование. Но в некоторых случаях можно, а иногда и нужно уйти от наследования.
                                                                                                                                                                              Цитата Fester @
                                                                                                                                                                              Это ради бога, вот только есть верить hh.ru, то этот D нахрен никому не нужен, а значит нет смыла тратить на него свое время
                                                                                                                                                                              Я уже писал, что такой же фокус можно провернуть как минимум на Ruby и на PHP. Ну и если верить hh.ru то и Rust "нахрен никому не нужен, а значит нет смыла тратить на него свое время". :lol: А вакансии для D периодически мелькают на форуме D.
                                                                                                                                                                              Ну и в конце-концов, список-то довольно внушительный: Organizations using the D Language
                                                                                                                                                                              Цитата OpenGL @
                                                                                                                                                                              Небось это контора applegame и искала спецов
                                                                                                                                                                              Не, контора applegame не ищет (и не искала) никаких спецов, а в данный момент вообще плотно обмазалась Elixir-ом. :)
                                                                                                                                                                              Сообщение отредактировано: applegame -
                                                                                                                                                                                Цитата applegame @
                                                                                                                                                                                Известная проблема Круга-Эллипса. Когда Круг является Эллипсом, но наследовать Круг от Эллипса - очень плохая идея.

                                                                                                                                                                                Имхо, надуманная проблема. Наследование тогда хорошо, когда оно как минимум дополняет предка свойствами или методами. Для задание фигуры "круг" - параметров нужно меньше, чем для задания фигуры "элипс". Вывод однозначен - элипс наследуем от круга. Та же шляпа между "квадратом" и "прямоугольником". Да, можно сказать, что квадрат - частный случай прямоугольника. Не вопрос! Но для задания квадрата нужно меньше параметров, следовательно прямоугольник наследуем от квадрата. Тупо ради экономии в количестве полей.

                                                                                                                                                                                Возникает вопрос в другом, от кого что наследовать, если параметров не добавляется? Можно и квадрат, и окружность наследовать от точки. Но можно ведь и окружность наследовать от квадрата (и наоборот). И там и там есть два параметра - точка позиционирования и второй параметр, сторона или радиус. С точки зрения кодирования - быстрее будет не от точки, ибо параметры не нужно будет N-раз прописывать. Вот тут наверное то место, где выгоднее все же прописать похожие параметры (иными словами наследоваться от точки), иначе потомки проклянут.
                                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                                  Ну и если верить hh.ru то и Rust "нахрен никому не нужен, а значит нет смыла тратить на него свое время"


                                                                                                                                                                                  А-я-яй! Врешь и не краснеешь :lol: На первой же странице:

                                                                                                                                                                                  user posted image
                                                                                                                                                                                    Цитата applegame @
                                                                                                                                                                                    Ну это камень в другой огород. Не в огород наследования.

                                                                                                                                                                                    Ууууу! Не видел ты, как из этой проблемы вырастали кадавры в которых ямы и лопаты наследовались от абстрактных "сущностей", а потом сливались в жарких объятьях в чем-то вроде "бытия", через которое можно было и копать яму лопатой, и наоборот ямой копатить, и вообще :D Но это я так, лирически набрасываю :)

                                                                                                                                                                                    Добавлено
                                                                                                                                                                                    Цитата applegame @
                                                                                                                                                                                    а в данный момент вообще плотно обмазалась Elixir-ом.

                                                                                                                                                                                    В котором нет никакого наследования вообще :)
                                                                                                                                                                                      Цитата JoeUser @
                                                                                                                                                                                      Та же шляпа между "квадратом" и "прямоугольником". Да, можно сказать, что квадрат - частный случай прямоугольника. Не вопрос! Но для задания квадрата нужно меньше параметров, следовательно прямоугольник наследуем от квадрата. Тупо ради экономии в количестве полей.

                                                                                                                                                                                      Вот тут автор предлагает другое решение: https://dou.ua/lenta/articles/composition-v...itance-in-java/
                                                                                                                                                                                      Ну там он в принципе призывает отказываться от наследования. И приводит пример в самом начале.
                                                                                                                                                                                      Цитата

                                                                                                                                                                                      То, что квадрат является частным случаем прямоугольника никоим образом не означает, что должна быть иерархия классов и наследование. Нам достаточно интерфейса Фигура и класса Прямоугольник, который его реализует. Нет причин не сделать его иммутабельным, без сеттеров, с конструктором на два аргумента. Для частного случая — квадрата — может быть либо конструктор с одним аргументом, либо, что лучше, как рекомендует Блох, статический фабричный метод с названием.
                                                                                                                                                                                        Мне одному кажется, что в случае с квадратами и прямоугольниками начать следует с вопросов о том, какие еще будут сущности, что вообще делаем, какую задачу в итоге решаем, и только потом уже начинать за наследование, классы и прочую агрегацию? :huh:
                                                                                                                                                                                        Сообщение отредактировано: Астарот -
                                                                                                                                                                                          Цитата applegame @
                                                                                                                                                                                          Когда Круг является Эллипсом, но наследовать Круг от Эллипса - очень плохая идея.

                                                                                                                                                                                          Зависит от интерфейсов. В случае иммутабельных объектов - норм.
                                                                                                                                                                                            Цитата D_KEY @
                                                                                                                                                                                            В случае иммутабельных объектов - норм.

                                                                                                                                                                                            Тыщастопицот объектов-"кругов" будут занимать больше памяти за счет лишнего параметра.
                                                                                                                                                                                              Цитата Астарот @
                                                                                                                                                                                              В котором нет никакого наследования вообще
                                                                                                                                                                                              Подобие интерфейсов зато есть - https://elixirschool.com/ru/lessons/advanced/protocols/
                                                                                                                                                                                              Цитата JoeUser @
                                                                                                                                                                                              А-я-яй! Врешь и не краснеешь На первой же странице:
                                                                                                                                                                                              Врешь и не краснеешь, потому что я покраснел когда врал! :D
                                                                                                                                                                                                Цитата Wound @
                                                                                                                                                                                                Вот тут автор предлагает другое решение: https://dou.ua/lenta/articles/composition-v...itance-in-java/
                                                                                                                                                                                                Ну там он в принципе призывает отказываться от наследования. И приводит пример в самом начале.

                                                                                                                                                                                                Ни коем разом не противоречит мною написанному! Я просто расписал как правильно наследоваться в "придуманной проблеме", но не обсуждал - нужно ли это делать, или же можно решить проблему вообще иначе.

                                                                                                                                                                                                Добавлено
                                                                                                                                                                                                Да и ващще, Бритва Оккама рулит!
                                                                                                                                                                                                И в определении последовательности наследования - рулит не менее!
                                                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                                                  Подобие интерфейсов зато есть

                                                                                                                                                                                                  Поведение из эрланга, я так понимаю?
                                                                                                                                                                                                    Цитата Астарот @
                                                                                                                                                                                                    Поведение из эрланга, я так понимаю?
                                                                                                                                                                                                    Нет, это чисто эликсировская хрень, поведение - это совсем другое.
                                                                                                                                                                                                    Сообщение отредактировано: applegame -
                                                                                                                                                                                                      Скрытый текст
                                                                                                                                                                                                      Цитата applegame @
                                                                                                                                                                                                      Врешь и не краснеешь, потому что я покраснел когда врал!

                                                                                                                                                                                                      :good:
                                                                                                                                                                                                        Цитата Астарот @
                                                                                                                                                                                                        Мне одному кажется, что в случае с квадратами и прямоугольниками начать следует с вопросов о том, какие еще будут сущности, что вообще делаем, какую задачу в итоге решаем, и только потом уже начинать за наследование, классы и прочую агрегацию?

                                                                                                                                                                                                        Не, не одному :) Любая задача жи начинается с осмысления, с построения более менее непротиворечивой и полной системы. Выдуманная и, увы, распространенная "проблема" наследования квадрата и прямоугольника - имхо, это очередной сферический конь в вакууме.
                                                                                                                                                                                                          Цитата JoeUser @
                                                                                                                                                                                                          Выдуманная и, увы, распространенная "проблема" наследования квадрата и прямоугольника - имхо, это очередной сферический конь в вакууме.
                                                                                                                                                                                                          Очевидно же, что это не проблема в смысле "сложная задача, которую трудно решить", это просто синтетический пример того, что вот этот вот тезис:
                                                                                                                                                                                                          Цитата JoeUser @
                                                                                                                                                                                                          1) Наследование используется, если имеем отношение "является"

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

                                                                                                                                                                                                          Вы же с Астаротом, похоже, восприняли эту "проблему" как некую критику наследования или хз что вы там подумали.
                                                                                                                                                                                                          Сообщение отредактировано: applegame -
                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                            Вы же с Астаротом, похоже, восприняли эту "проблему" как некую критику наследования или хз что вы там подумали.

                                                                                                                                                                                                            Лично я эту "проблему" воспринял так, что если это абстрактная проблема, то решать ее можно как угодно, а если реальная, то начинать решать надо совсем с другого :-?

                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                            Барбара Лисков предложила довольно простой принцип.

                                                                                                                                                                                                            Принцип-то простой, но куда его прикладывать на практике я так до конца и не вкурил :(
                                                                                                                                                                                                            Сообщение отредактировано: Астарот -
                                                                                                                                                                                                              Цитата Астарот @
                                                                                                                                                                                                              Лично я эту "проблему" воспринял так, что если это абстрактная проблема, то решать ее можно как угодно, а если реальная, то начинать решать надо совсем с другого
                                                                                                                                                                                                              Воспринимай эту "проблему" точно также как ты воспринимал вот эту :)
                                                                                                                                                                                                              Цитата Астарот @
                                                                                                                                                                                                              Есть еще более классическая фигня - лопата копает яму, или яма копается лопатой?

                                                                                                                                                                                                              Цитата Астарот @
                                                                                                                                                                                                              Принцип-то простой, но куда его прикладывать на практике я так до конца и не вкурил
                                                                                                                                                                                                              А в чем трабла? Собрался наследовать B от A. Подумай, сможешь ли во все методы предназначенные для A корректно засунуть любой B. Если сможешь, все ок, если нет - что-то пошло не так.
                                                                                                                                                                                                              Сообщение отредактировано: applegame -
                                                                                                                                                                                                                Цитата Астарот @
                                                                                                                                                                                                                но куда его прикладывать на практике я так до конца и не вкурил :(

                                                                                                                                                                                                                К отношениям :)
                                                                                                                                                                                                                Вот если объект класса B может всегда и везде выступать как объект класса A, если контракты B полностью соответствуют контрактам A (в случае методов можно ослаблять предусловия и усиливать постусловия), тогда и применимо наследование :-?
                                                                                                                                                                                                                Сообщение отредактировано: D_KEY -
                                                                                                                                                                                                                  Цитата applegame @
                                                                                                                                                                                                                  А в чем трабла? Собрался наследовать B от A. Подумай, сможешь ли во все методы предназначенные для A корректно засунуть любой B. Если сможешь, все ок, если нет - что-то пошло не так.

                                                                                                                                                                                                                  Проблема в том, что методов принимающих А много, и не все они писаны мной, поэтому, как проверить, что все ок не понятно.

                                                                                                                                                                                                                  Цитата D_KEY @
                                                                                                                                                                                                                  Вот если объект класса B может всегда и везде выступать как объект класса A, если контракты B полностью соответствуют контрактам A (в случае методов можно ослаблять предусловия и усиливать постусловия), тогда и применимо наследование

                                                                                                                                                                                                                  Что за "пред" и "пост" условия такие? :scratch:
                                                                                                                                                                                                                    Цитата Астарот @
                                                                                                                                                                                                                    Есть еще более классическая фигня - лопата копает яму, или яма копается лопатой?

                                                                                                                                                                                                                    В этом мире человек копает яму лопатой. =)
                                                                                                                                                                                                                      Цитата korvin @
                                                                                                                                                                                                                      Цитата Астарот @
                                                                                                                                                                                                                      Есть еще более классическая фигня - лопата копает яму, или яма копается лопатой?

                                                                                                                                                                                                                      В этом мире человек копает яму лопатой. =)

                                                                                                                                                                                                                      Хм. И как следует описать этот твой тезис:
                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                        яма = Яма.создать<Лопата>()

                                                                                                                                                                                                                      или
                                                                                                                                                                                                                      ExpandedWrap disabled
                                                                                                                                                                                                                        яма = Лопата.создать<Яма>()

                                                                                                                                                                                                                      :lol:
                                                                                                                                                                                                                      Сообщение отредактировано: applegame -
                                                                                                                                                                                                                        ExpandedWrap disabled
                                                                                                                                                                                                                          яма = Бог.создать<Человек>().создать<Лопата>().создать<Яма>()

                                                                                                                                                                                                                        :ph34r:
                                                                                                                                                                                                                        Сообщение отредактировано: Астарот -
                                                                                                                                                                                                                          Цитата Астарот @
                                                                                                                                                                                                                          Что за "пред" и "пост" условия такие? :scratch:

                                                                                                                                                                                                                          Это контракты. DbC и все такое.

                                                                                                                                                                                                                          У функций/методов есть предусловия - набор требований, которые должны быть обеспечены вызывающей стороной, и постусловия - набор условий, выполнение которых мы гарантируем по окончании вызова.
                                                                                                                                                                                                                          Например. Вот есть у нас очередь и мы хотим запихнуть в нее элемент. Мы можем требовать, чтобы очередь не была заполненной (допустим, это имеет смысл), а со своей стороны можем гарантировать, что очередь будет не пуста.

                                                                                                                                                                                                                          Вот как это выглядит в предложении к стандартизации для C++:
                                                                                                                                                                                                                          ExpandedWrap disabled
                                                                                                                                                                                                                            int push(queue& q, int val)
                                                                                                                                                                                                                              [[ expects: !q.full() ]]
                                                                                                                                                                                                                              [[ ensures !q.empty() ]]{
                                                                                                                                                                                                                              ...
                                                                                                                                                                                                                            }

                                                                                                                                                                                                                          Для java точно есть решения.

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

                                                                                                                                                                                                                          Есть еще инварианты, но про них, я думаю, ты слышал.
                                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                                            И как следует описать этот твой тезис
                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                              яма = Яма.создать<Лопата>()


                                                                                                                                                                                                                            В этом мире ямы не создаются сами по себе. Их создают люди. Или другие животные. Зачем при этом параметризовать яму лопатой совсем не понятно.

                                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                                            или
                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                              яма = Лопата.создать<Яма>()

                                                                                                                                                                                                                            Оружие не убивает, убивают люди. Т.е. лопаты не создают ямы. См. выше.

                                                                                                                                                                                                                            ExpandedWrap disabled
                                                                                                                                                                                                                              type Яма = ...
                                                                                                                                                                                                                              type КопательныйИнструмент = ...
                                                                                                                                                                                                                              type Размеры = ...
                                                                                                                                                                                                                               
                                                                                                                                                                                                                              class Человек : object
                                                                                                                                                                                                                                ...
                                                                                                                                                                                                                                method копать_яму_с_помощью : КопательныйИнструмент -> Размеры -> Яма
                                                                                                                                                                                                                                method копать_яму_конечностями : Размеры -> Яма
                                                                                                                                                                                                                              end
                                                                                                                                                                                                                               
                                                                                                                                                                                                                              let applegame = new Человек ... in
                                                                                                                                                                                                                              let лопата = new Лопата ... in
                                                                                                                                                                                                                                большущая_яма = applegame#копать_яму_с_помощью лопата (Размеры ...)
                                                                                                                                                                                                                              Цитата korvin @
                                                                                                                                                                                                                              В этом мире

                                                                                                                                                                                                                              Согласно твоей модели мира :)
                                                                                                                                                                                                                                Цитата JoeUser @
                                                                                                                                                                                                                                И как его зафэйлить? Приведи пример, плс.
                                                                                                                                                                                                                                Ты, походу, вообще не понял, объчём речь. Иначе зачем вместо развития интерфейсов реализовал их?
                                                                                                                                                                                                                                  Цитата Qraizer @
                                                                                                                                                                                                                                  Ты, походу, вообще не понял, объчём речь.

                                                                                                                                                                                                                                  :(
                                                                                                                                                                                                                                    Цитата D_KEY @
                                                                                                                                                                                                                                    Согласно твоей модели мира

                                                                                                                                                                                                                                    Ну, не знаю, как у вас там на Альфа-Центавре, но у нас пока что лопаты не обладают автономностью и хоть каким-нибудь интеллектом, чтобы копать самостоятельно. Хотя, если речь о мире Микки Мауса, например, или какой-то компьютерной игре, то там, конечно всякое может быть, ямы и сами могут копать себя без всяких лопат.

                                                                                                                                                                                                                                    Just for fun

                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                      type location =
                                                                                                                                                                                                                                          { lat : float
                                                                                                                                                                                                                                          ; lon : float
                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let location_to_string { lat ; lon } =
                                                                                                                                                                                                                                          Printf.sprintf "(lat %.2f, lon %.2f)" lat lon
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      type size =
                                                                                                                                                                                                                                          { length : float
                                                                                                                                                                                                                                          ; width : float
                                                                                                                                                                                                                                          ; height : float
                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let size_to_string { length ; width ; height } =
                                                                                                                                                                                                                                          Printf.sprintf "(LxWxH = %.1fx%.1fx%.1f)" length width height
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      type pit =
                                                                                                                                                                                                                                          { size : size
                                                                                                                                                                                                                                          ; location : location
                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let pit_to_string { size ; location } =
                                                                                                                                                                                                                                          Printf.sprintf "Pit of %s at %s" (size_to_string size) (location_to_string location)
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      type capacity =
                                                                                                                                                                                                                                          { volume : size
                                                                                                                                                                                                                                          ; weight : float
                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      type dig_tool = < capacity : capacity >
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      (* just a helper functions for more DSL'ish syntax *)
                                                                                                                                                                                                                                      let at_ x = x
                                                                                                                                                                                                                                      let of_ x = x
                                                                                                                                                                                                                                      let with_ x = x
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      class shovel volume_capacity weight_capacity = object
                                                                                                                                                                                                                                          method capacity = { volume = volume_capacity ; weight = weight_capacity }
                                                                                                                                                                                                                                      end
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      class hand (cap : capacity) = object
                                                                                                                                                                                                                                          method capacity = cap
                                                                                                                                                                                                                                          method side_by_side (other_hand : hand) =
                                                                                                                                                                                                                                              let l = min cap.volume.length (other_hand#capacity).volume.length in
                                                                                                                                                                                                                                              let w = cap.volume.width +. (other_hand#capacity).volume.width in
                                                                                                                                                                                                                                              let h = min cap.volume.height (other_hand#capacity).volume.height in
                                                                                                                                                                                                                                              let wc = cap.weight +. (other_hand#capacity).weight in
                                                                                                                                                                                                                                                  object
                                                                                                                                                                                                                                                      method capacity = { volume = { length = l ; width = w ; height = h } ; weight = wc }
                                                                                                                                                                                                                                                  end
                                                                                                                                                                                                                                      end
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      class human (left_hand : hand) (right_hand : hand) = object (self)
                                                                                                                                                                                                                                          method private both_hands = left_hand#side_by_side (with_ right_hand)
                                                                                                                                                                                                                                          method dig_a_pit_with dig_tool size location =
                                                                                                                                                                                                                                              { size = size ; location = location }
                                                                                                                                                                                                                                          method dig_a_pit size location =
                                                                                                                                                                                                                                              self#dig_a_pit_with (self#both_hands) size location
                                                                                                                                                                                                                                      end
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let a_small_shovel = new shovel { length = 20.0 ; width = 15.0 ; height = 3.0 } 1.5
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let a_strong_hand = new hand { volume = { length = 15.0 ; width = 10.0 ; height = 5.0 }
                                                                                                                                                                                                                                                                   ; weight = 3.0
                                                                                                                                                                                                                                                                   }
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let a_huge_size =
                                                                                                                                                                                                                                          { length = 100.0
                                                                                                                                                                                                                                          ; width = 200.0
                                                                                                                                                                                                                                          ; height = 50.0
                                                                                                                                                                                                                                          }
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let the_center_of_moscow = { lat = 1.23 ; lon = 45.6 }
                                                                                                                                                                                                                                      let the_center_of_saint_petersburg = { lat = 12.3 ; lon = 4.56 }
                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                      let _ =
                                                                                                                                                                                                                                          let applegame = new human (with_ a_strong_hand) (with_ a_strong_hand) in
                                                                                                                                                                                                                                          let a_great_pit_in_moscow = applegame#dig_a_pit_with a_small_shovel (of_ a_huge_size) (at_ the_center_of_moscow) in
                                                                                                                                                                                                                                          let a_great_pit_in_saint_pete = applegame#dig_a_pit (of_ a_huge_size) (at_ the_center_of_saint_petersburg) in
                                                                                                                                                                                                                                          Printf.printf "%s\n" (pit_to_string a_great_pit_in_moscow) ;
                                                                                                                                                                                                                                          Printf.printf "%s\n" (pit_to_string a_great_pit_in_saint_pete)


                                                                                                                                                                                                                                    ExpandedWrap disabled
                                                                                                                                                                                                                                      Pit of (LxWxH = 100.0x200.0x50.0) at (lat 1.23, lon 45.60)
                                                                                                                                                                                                                                      Pit of (LxWxH = 100.0x200.0x50.0) at (lat 12.30, lon 4.56)

                                                                                                                                                                                                                                    Сообщение отредактировано: korvin -
                                                                                                                                                                                                                                      Цитата korvin @
                                                                                                                                                                                                                                      Ну, не знаю, как у вас там на Альфа-Центавре, но у нас пока что лопаты не обладают автономностью и хоть каким-нибудь интеллектом, чтобы копать самостоятельно.

                                                                                                                                                                                                                                      Ну я к тому, что "человек", "яма", "лопата" и даже твоя "автономность" и "интеллект" - это абстракции, т.е. часть модели мира, а не сам мир :)
                                                                                                                                                                                                                                        Цитата D_KEY @
                                                                                                                                                                                                                                        Ну я к тому, что "человек", "яма", "лопата" и даже твоя "автономность" и "интеллект" - это абстракции, т.е. часть модели мира, а не сам мир

                                                                                                                                                                                                                                        Ой вей, в чём тогда проблема? Делай как тебе нравится. Хоть интеллектуальную лопату, хоть самовыкапывающуюся яму.
                                                                                                                                                                                                                                          Цитата korvin @
                                                                                                                                                                                                                                          Ой вей, в чём тогда проблема? Делай как тебе нравится. Хоть интеллектуальную лопату, хоть самовыкапывающуюся яму.
                                                                                                                                                                                                                                          Астарот говорит, если делать как тебе нравится, а не как правильно (а как правильно?) то мертвые могут восстать из могил.
                                                                                                                                                                                                                                            Цитата applegame @
                                                                                                                                                                                                                                            Астарот говорит, если делать как тебе нравится, а не как правильно (а как правильно?) то мертвые могут восстать из могил.

                                                                                                                                                                                                                                            Я говорю как раз наоборот - делай так, что б решить свою проблему и достичь поставленной цели. И если при этом мертвые восстанут из могил, то что с того? :rolleyes:
                                                                                                                                                                                                                                              Цитата Астарот @
                                                                                                                                                                                                                                              Я говорю как раз наоборот - делай так, что б решить свою проблему и достичь поставленной цели. И если при этом мертвые восстанут из могил, то что с того?
                                                                                                                                                                                                                                              Тогда проблемы ямы и лопаты не существует. :) И вообще никаких проблем не существует. :lol:
                                                                                                                                                                                                                                              Сообщение отредактировано: applegame -
                                                                                                                                                                                                                                                Цитата applegame @
                                                                                                                                                                                                                                                Тогда проблемы ямы и лопаты не существует. :)

                                                                                                                                                                                                                                                Конечно не существует. Что, однако, не мешает ломать над ней копья :D
                                                                                                                                                                                                                                                  Цитата Астарот @
                                                                                                                                                                                                                                                  Что, однако, не мешает ломать над ней копья

                                                                                                                                                                                                                                                  Лишь бы не лопаты
                                                                                                                                                                                                                                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                                                                                                                                                                                  0 пользователей:


                                                                                                                                                                                                                                                  Рейтинг@Mail.ru
                                                                                                                                                                                                                                                  [ Script execution time: 0,2903 ]   [ 18 queries used ]   [ Generated: 24.04.24, 04:41 GMT ]