В защиту ООП. 7 несостоятельных аргументов его противников

Когда я, так сказать, прошёлся по Интернету, я заметил одну интересную особенность. Все парадигмы программирования, где-либо обсуждаемые, воспринимаются людьми совершенно спокойно. Если, например, говорят про процедурное программирование, то говорят про него абсолютно спокойно. То же самое — про модульное программирование. Декларативное программирование — никаких бурь, волнений или холиваров. Функциональное программирование — то же самое.

И только вокруг ООП не утихают бури. Одни визжат от него в восторге, другие, наоборот, хаят на чём свет зиждется. И мне, честно сказать, совершенно непонятно, почему на ООП весь мир клином сошёлся.

Возможно, вы только что подумали, что я — скорее противник, чем сторонник ООП. Это абсолютно не так (впрочем, вы это можете понять из заголовка). Нет. Я — скорее противник «серебряных пуль», хайпа, возведения какой-либо методологии или человека на престол и всяческого вождения хороводов. Вы же не водите хороводы вокруг, скажем, гаечного ключа или газонокосилки. И не пишете, я надеюсь, публикаций, почему дрель или молоток — отстой.
Но на сегодняшний день весь Интернет кишит именно напыщенными, гиперэмоциональными, радикалистскими статьями по поводу ООП — если один говорит, что ООП — «зер гут» и вообще всем гутам гут — то другой обязательно вещает, что ООП необходимо срочно выкинуть на помойку (если только он не разделяет взгляды первого). Третьего не дано.

Я же хочу именно привнести третий элемент. Спокойно, без хайпа и ругани рассказать, почему ООП — не эликсир от всех болезней, но также, как и ПП, ФП или ЛП имеет право на существование.

Итак, спокойная статья в защиту ООП. В ней я попытаюсь рассмотреть основные доводы противников ООП и обосновать их несостоятельность.

1. Всё, что есть в ООП, уже давно есть в других парадигмах


Почти все языки программирования являются тьюринг-полными, за исключением языков разметок, как то: HTML, XML, CSS и т.д. Если говорить крестьянским языком, тьюринг-полный язык — язык, на котором можно написать абсолютно любую мыслимую программу. Из этого следует довольно-таки всеобщий тезис: то, что есть в любом наудачу выбранном языке, есть во всех остальных языках. То же можно сказать и про парадигмы. Все отличия языков (и парадигм) — это разные способы реализации тех или иных команд, не считая отдельных лексических особенностей.

Кстати, этот же тезис (всё, что есть в N, есть и в M, и в K, и в R и т.д.) можно сформулировать так: молоток уже состоит из железа да дерева, зачем же нам ещё и пассатижи? Но ведь так никто не станет утверждать.

2. ООП смешивает данные и действия над ними. Это плохо


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

3. Наследование закрепощает программу, делает трудным внесение изменений


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

Если не предполагается расширять родительский класс третьим классом — такое наследование попросту бессмысленно. Если вы создаёте магазин спиртных напитков, то классы Beer, Vodka и Vine можно унаследовать от класса Alcohol, но совершенно не нужно создавать ещё и класс Drinks, если только вы не хотите продавать ещё и, скажем, парагвайский чай.

Также ошибкой будет создание иерархий, в которых классы никак не относятся друг к другу. Ну зачем, расскажите мне, городить башню, где классы Муха и Котлета наследуются от суперкласса Сыр, который, в свою очередь, наследуется от суперкласса Пятница?! Но это уже не недостаток ООП, а кривые руки того, кто такое сочиняет.

4. Инкапсуляция не имеет смысла


Вот тут я частично согласен. С точки зрения работы программы инкапсуляция действительно ни на что не влияет. Если я закрою переменную с помощью private — ну и что, я всё равно смогу её открыть, просто убрав private, а потом менять там всё, что душе заблагорассудится.

Но это верно лишь чисто технически. Философия ООП гласит: правильно организованный и инкапсулированный класс можно рассматривать как чёрный ящик. Представьте себе коробку, на одной стороне которой разнообразные кнопки, слоты для подачи данных, а на другой — выходной слот, который возвращает информацию. Возьмём, к примеру, стек. Представьте коробку, на одной стороне которой есть один слот для вставки данных и кнопка push рядышком. На обратной стороне — кнопка pop. Вы подаёте туда записку с числом 8 и давите кнопку push. Затем подаёте ещё бумажку и второй раз давите push. И так N раз, а затем жмёте pop. Из ящика вылетает бумажка с числом 76 (или другое, в общем, то, которое вы подали). Нужно ещё число? Второй раз давите pop. И так до морковкина заговенья тех пор, пока ящик не опустеет. А если вы продолжите давить pop, механизм из ящика завоет: стек пуст! Именно так и выглядит объект.

Но после того, как вы создали и настроили класс, вам уже фиолетово, как он там работает — он просто правильно работает, а большего и желать не нужно. А инкапсулируя все эти структуры, вы не держите всё подряд в памяти. Они (множество ящиков) просто общаются между собой так, как вы настроите.

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

Хотя, вряд ли это «увы» здесь вообще уместно.

5. В реальном мире нет иерархий отношения, повсюду лишь иерархии включения


Да разве? Но ведь никто не мешает создать, например, иерархию, где все реки мира (Конго, Сена, Темза, Амазонка, Колыма и т.д.) являются объектами одной всеобъемлющей «Реки», которой присущи свойства (например, состоит из воды) и действия (например, течёт), а уже она будет наследоваться от «Водоёма», который тоже состоит из воды, а от «Водоёма» можно унаследовать ещё и «Озеро», объектами которого будут отдельные озёра (Байкал, Каспийское море, Титикака и т.д.). Схема довольно грубая. Но иерархии отношения — это тоже абстракция. Что-то а-ля платоновской идеи, если хотите. В реальном мире их нет, они существуют только в уме, это обобщение, и не более того. Но ведь именно так человек очень часто мыслит. Мы ведь можем сказать «носок», без уточнения, каков у него цвет, из какого материала соткан и т.д., но существует ли этот «носок» в действительности?

И всё же нас не должно смущать, что нет ни «объекта», ни «носка».

6. Методология ООП изначально ошибочна


Абсолютно необоснованный аргумент. ООП создавалось для того, чтобы моделировать своеобразный виртуальный мир, состоящий из объектов, как и наш мир. Например: человек — объект из реального мира. Он может ходить, бегать, кушать, срать спать, играть в футбол, смотреть футбол, но, к сожалению, я тут не могу всё перечислить, да и, честно сказать, всё перечислять было бы противно. Этот же самый человек обладает свойствами: наличие/отсутствие волос, цвет волос, если они есть, цвет глаз, если они есть цвет кожи, количество пальцев на руках и т.д. Если правильно сконструировать все поля и методы, как я уже писал выше, то программный объект сможет моделировать те или иные свойства реального объекта. Человек очень даже хорошо мыслит в таких категориях — именно поэтому ООП и стало распространённым. Оно очень помогает при написании больших проектов, так как привносит модульность и позволяет разбивать программный пакет на отдельные компоненты, взаимодействующие друг с другом.

7. Но даже миллионы мух не убедят нас, что навоз — это вкусно


Самый популярный аргумент против ООП. Мол, массы в большинстве своём глупы (всё же я не думаю, что это относится и к программистам), бегают по «модным шмоткам» и восхищаются ими.
Но задумайтесь, а если бы на пьедестал взошло не ООП, а, скажем, ЛП? Думаете, было бы всё по-другому? Ничего подобного! Нашлись бы и фанаты, и злостные противники, а на ООП смотрели бы как на инструмент (к этому я, вообще-то, и призываю), а не как на таблетку, сотворённую самим Богом и потому незаменимую.



Почему эта статья — в защиту ООП?


Все современные разговоры про парадигмы программирования, как мне видится, сводятся к двум диаметральным посылкам: оставим ООП и выкинем всё остальное, или же выкинем ООП и… ну, вы поняли меня.

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

Если вам не нравится ООП


Кому — ООП, кому — ФП, кому — ПП. А кому-нибудь, может быть, вообще более всего мил свиной хрящик. Если вы не любите кошек — наверное, вы просто не умеете их готовить.
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 395

    0
    Одна из существенных проблем ООП, кмк, — реализация операций. То есть на классическую парадигму оно очень плохо ложится. Сложение чисел или конкатенация — тому яркий пример: objA.plus(objB) или objB.plus(objA)? (я в курсе про хелперы, но их существование не укладывается в классическую парадигму).

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

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

    Наследование — тоже хорошо там, где оно уместно. Проблема только в том, что оно резко сжимает пространство маневра при разработке сложных систем, композиция гибче. В реальной жизни мы используем одни и те же предметы как принадлежащие разным иерархиям наследования, просто не задумываемся об этом. В ООП же объект может принадлежать только одной иерархии (про cpp в курсе).
      +3
      Реализация операций не зависит от ООП и в некоторых языках решается перегрузкой операторов.
        –3
        Проблема тут не в реализации, а в том как обеспечить полиморфизм.
          0
          Наверное, все-таки разговор про иммутабельность?
            –1
            В первом абзаце — нет, не про иммутабельность.
    • UFO just landed and posted this here
        0
        тому яркий пример: objA.plus(objB) или objB.plus(objA)? (я в курсе про хелперы, но их существование не укладывается в классическую парадигму).

        Не совсем понимаю где проблема.


        std::string a("123");
        std::string b("444");
        const std::string a{"123123"};
        
        std::string c{a+b};
        std::string d{b+a};
        
        a+=aa;
        
        aa+="xxx"; // compiler throws an error here

        По моему всё семантически чётко и ясно. Или всё-таки где-то проблемы?

          0
          >>const std::string a{«123123»};

          должно быть
          const std::string aa{«123123»};
            0
            Что делать, если мне часто нужно переворачивать строку?
            Писать метод в функциональном стиле
            std::string reverse(const std::string& src);

            или в процедурном
            void reverse(std::string& str);

            Но в ООП это никак не заходит.
              +1

              Угу опять вопрос мутабельности. Это холивар. А утилитарно всё зависит от цели:


              1. std::reverse() — swap
              2. std::string::rbegin() — реверсный итератор
              3. std::string::crbegin — константный реверсный итератор

              Вы действительно считаете, что эта проблема "буриданова осла", кого-то остановит от желания программировать на C++ или в ООП парадигме в целом? Дать право программисту выбрать длительность жизненного цикла объекта и доступа к нему, или отобрать? Совсем! Чтоб неповадно было.


              Вопрос выбора инструмента, дело каждого конкретного программиста. Всё это вкусовщина. Небо наземлю не упадёт если объекты будут mutable.


              Вот вам гениальный пример для батхёрта (пусть стошнит каждого функциональщика):


              class A {
                mutable std::mutex __mutex;
                std::string              __str;
              public:
                void  set(const std::string& str)
                {
                   std::lock_guard<std::mutex> sync(__mutex);
                  __str=str;
                }
                const std::string get() const
                {
                   std::lock_guard<std::mutex> sync(__mutex);
                   return __str;
                }
              };

              Ух пронесло, — небо не упало!


              Вы не поверите, люди до сих пор пишут на чистом C! Тут в ветке даже Дельфисты отметились.


              Вам шашечки или ехать?

                +1
                кого-то остановит от желания программировать на C++ или в ООП парадигме в целом?
                На C++ можно программировать и в функциональном стиле.

                Вам шашечки или ехать?
                Я отвечал на
                >> objA.plus(objB) не укладывается в классическую парадигму
                > Не совсем понимаю где проблема

                Что есть неудобства в ООП, когда объекты предоставлены из внешней (стандартной) библиотеки, и тут приходится съезжать на ПП или ФП.

                Сам-то я не против ООП, но не отрицаю его проблемы.
                    0
                    Это типа extension methods, подсмотренные в c#?
                      0
                      Там же чёрным по белому написано: любую функцию можно вызвать как метод её первого аргумента.
                        0
                        Если это способ реализовать недостающие функции объектов, к коду которых нет доступа, то это просто костыль, синтаксический сахар ))

                        В сравнении с полноценным наследованием, тут недоступны protected-поля и методы, оставленные автором объекта для расширения его функциональности. Нельзя добавить новое поле, и т.п. ограничения.
                          0
                          То, о чём вы говорите — это уже monkey patching и от него больше вреда, чем пользы.
                          0

                          Любую мономорфную функцию в языке без подтипирования.
                          Все-таки при формулировке теоремы не стоит забывать про условия.

                +1
                семантически чётко и ясно. Или всё-таки где-то проблемы?
                Это потому что конкатенация предусмотрена создателями библиотеки std. Но описание перегрузки оператора умножения над двумя std::vector«double», чтобы считалось скалярное произведение, выходит за рамки ООП.
                  0

                  Вы наверное имели в виду STL. И что вам мешает следовать хорошему тону STL, и писать такие-же библиотеки. В STL кстати есть functional в котором в том числе ести и функциональный класс std::multiplies.


                  Самое главное, вас ведь никто не ограничивает писать то как вы хотите и как считаете нужным, главное что-бы вам удобно было. А зависать над вопросом "в какой парадигме мне это реализовать", — не продуктивно. Выбирайте хоть ФП, хоть ООП, хоть haskel хоть Java. И реализуйте это то как считаете верным. Какой смысл в войне между отвёрткой и гаечным ключём? Никакой! И тот и другой инструмент может понадобится.

                0

                Операторы — парадигма математической записи. И она плохо ложится на программирование.


                Как только появляется возможность использовать несколько операторов в одной строке [не нашел нужного научного термина, но думаю суть понятна] — волосы начинают шевелиться.

                  0
                  несколько операторов в одной строке [не нашел нужного научного термина, но думаю суть понятна]

                  Кортеж?
                    0

                    кортеж это форма хранения, а не записи

                  +1
                  Разумеется модифицировать существующий. Мембер принадлежит обьекту, значит и работает он с обьектом, какой то вопрос глупый, с чего бы вообще операции создавать новый обьект новый обьект создается конструктором, или фабрикой или мембером который явно определяет создание новое обьекта если мы говорим о колекции но никак операция над обьектом не должна создавать явно новый обьект оке мы можем создать мутабл переменную но в общем случае конечный программист использующий интерфейс обьекта об этом никогда не думает, ну и с каких пор обьектно ориентированное программирование использует plus? Это что за сумрачный гений это придумал, есть функции которые нативно выглядят как операторы языка, и вообще что плохого в перегрузке, то что она неявная оргамунт уровня add неявно — разумеется если вы используете класс не интегрального(фундаментального типа) с перегрузкой оператора вы ожидаете особого поведения сематически эквивалетного сложения к примеру для матриц или строк, снова какие то обсолютно выдуманные аргументы в пользу фп и иммутабельности, ооп никогда не топил за создание новго объекта при действиях типа сложения и операция на сематическую адекватность, крч, снова проблемы возникающие в результате отсутсвия вопроса самому себе — а что должна делать функция и кривых интерфейсах.
                    +3

                    Вопрос не глупый. Например 1.Add(2) явно должен создавать новый объект 3, а не менять первый константный аргумент.

                      0

                      Это потому, что у вас слева rvalue. А вот так совсем не явно:


                      auto foo = 1
                      foo.Add(2) // foo += 2
                        0
                        у вас равно — это присвоение или алиас? Потому что если мы смували `1` в `foo`, а потом изменением его, то изменятся все единицы во всей программе. Это явно не то, чего мы хотим.
                          0

                          Присвоение, разумеется. Изменится лишь локальная переменная.

                            0
                            В общем, вы не правы в общем случае. Метод может модифицировать объект, но не обязан. Куча апи на этом построена, например вот.
                              0
                              А вот подменять тезисы, пожалуйста, не надо.
                                +1
                                Мембер принадлежит обьекту, значит и работает он с обьектом, какой то вопрос глупый, с чего бы вообще операции создавать новый обьект

                                Вопрос не глупый. Например 1.Add(2) явно должен создавать новый объект 3, а не менять первый константный аргумент.

                                Эмм, где подмена?
                                  0
                                  Логическое отрицание и антоним — разные вещи.
                    +1

                    Реализуете интерфейс Add и все. Сигнатура этого метода явно должна сказать, что происходит. Например вот.


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

                    Инкапсуляция — это вообще свойство любой программы в любой парадигме. Вот написали вы let loadFromDatabase = loadFrom database — инкапсулировали загрузку из бд! Только вот ООП тут ни на гран.


                    Наследование — тоже хорошо там, где оно уместно. Проблема только в том, что оно резко сжимает пространство маневра при разработке сложных систем, композиция гибче. В реальной жизни мы используем одни и те же предметы как принадлежащие разным иерархиям наследования, просто не задумываемся об этом. В ООП же объект может принадлежать только одной иерархии (про cpp в курсе).

                    Композиция и наследование ортогональны. Спросити у растовчан, насколько им приятно писать UI без наследования, услышите массу интересного.

                    +3
                    Если, например, говорят про процедурное программирование, то говорят про него абсолютно спокойно

                    Чистое процедурное программирование — это треш, угар и содомия с логарифмическим графом зависимостей скорости разработки от количества кода. Говоря проще: Больше кода и больше проблем, где-то в некой точке X переходящей в уничтожение как личности каждого, кто попытается добавить туда ещё какую-нибудь процедурку/функционал.

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

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

                    P.S. А на ООП сваливаются все камни по той причине, что это некое «над» решение, которое успешно совмещает (в реальной жизни имеется ввиду, а не сферическом ваккууме) под своим крылом и функциональщину, и процедурщину, и декларативное, аспектное, контрактное, прототипное и прочие программирования. Это стержень архитектуры, а остальное — это лишь решение частных мелких проблем/алогритмов (ФП — это вообще ярковыраженный представитель таких решений, где для решения частной задачи надо понаклепать с десяток функций, которые потом композицией выстраиваются в красивую программку).
                      0

                      Есть один подход, в котором процедурное программирование вполне себе удобно. Это языки-обязки над низкоуровневым кодом. Таким когда-то было PHP, и он выстрелил. Таким сейчас является Lua. Он тоже не имеет себе равных в некоторых узких областях применения.

                        +1
                        В процедурном подходе никто не мешает вам иметь локальные состояния. Более того, некоторые рассматривают ООП в целом лишь как идею организации процедурного кода, а ООП возможности языков как синтаксический сахар, без которого можно обойтись и написать что-то вроде GTK в парадигме ООП но без сахара.
                          +2
                          Напомните, на чём там написаны ядра linux, windows или freebsd?
                            0
                            Когда писались эти ядра, хорошо проработанной и реализованной концепции ООП еще не было. В результате получили такое чудо как Win API. Которое только Delphi смогло к более-менее удобоваримому и однообразному виду привести. Яркий пример, что может получится в результате использования ФП, к слову.
                              0
                              Странно приводить VCL как пример хорошей обёртки над WinAPI. VCL в Delphi ужасен и тянет груз совместимости с Win16. Было дело — использовал такую вещь как Watcom Optima — это тот же Delphi, только C++ и не отягощённый грузом совместимости — всё было гораздо проще, компактнее и по возможностям базовой библиотеки превосходило Delphi. (В своё время много использовал и Delphi и напрямую WinAPI и свои не-Delphi-йские компонентные системы над Win32 API делал и делал backports на Win16.)
                                0
                                Ну, первая версия ядра linux — 91 год, а C++ появился в 83. То есть времени для появления более-менее надёжных практик достаточно. А вот намного более поздняя HaikuOS уже в основном написана на C++ (кстати, BeAPI офигенная штука, намного удобнее WinAPI), хотя отдельные части всё ещё C.

                                Ещё пример: микроконтроллеры. Довольно мало любителей писать под них на плюсах. Ну, потому что ограничение ресурсов слишком жёсткое. Это уже не говоря про FPGA, где свой маленький мир.

                                И не забудьте про мои любимые шелл-скрипты, которые чуть менее, чем полностью состоят из процедурного подхода.

                                Я не говорю, что C++ и ООП плохо, просто есть места, где их использовать не стоит.
                                • UFO just landed and posted this here
                                  +2
                                  Не знаю кода этих ОС, но знаю код некоторых других проектов на С, и он похож на ООП подход. Например, если рассмотреть модульность ffmpeg (как в libavcodec). В ОС, мне кажется, не обойтись без объектного мышления.
                                  +5
                                  Чистое процедурное программирование — это треш, угар и содомия

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

                                  По-моему о процедурном подходе как раз и не говорят ничего плохого, т.к. это удел либо мелких одноразовых тулзовин

                                  Расскажите это: Линусу Торвальдсу или создателям почти любой ОС, создателям apache, nginx, tarantul, и т.д.


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

                                    +2
                                    Расскажите это: Линусу Торвальдсу или создателям почти любой ОС, создателям apache, nginx, tarantul, и т.д.
                                    Вот только они не написаны в чистом процедурном стиле. То что в C нет классов не значит что в нем нельзя использовать ООП.
                                    • UFO just landed and posted this here
                                        +1
                                        Да, большинство современных проектов на C реализованны именно в рамках объектно-ориентированной парадигмы. В ручную:)
                                    0
                                    Одна из существенных проблем ООП, кмк, — реализация операций. То есть на классическую парадигму оно очень плохо ложится. Сложение чисел или конкатенация — тому яркий пример: objA.plus(objB) или objB.plus(objA)

                                    Если перекладывать эту операцию на реальный мир, то всё зависит от того, что мы делаем. При наличии у нас двух коробок с апельсинами, мы можем переложить их из одной в другую, тем самым изменив состояния одной из коробок. При этом мы можем все апельсины переложить в третью коробку, тем самым создав новый объект (заодно выкидываем старые коробки). То есть всё зависит от конкретных требований.
                                      +1
                                      Я вообще слабо представляю системы порядка единиц/десятков миллиона строк кода написанных в фп парадигме. Как написавший 2/3 от нескольких миллиннострочных проектов.
                                      Также не совсем очевидны выгоды от иммутабельности. Возможно в каких-то случаях она полезна, сложно сказать. Как по мне — то проще найти кто меняет данные и разобраться с проблемами, чем запрещать мутабельность вообще. Может, конечно, языки такие, что это сделать сложно или невозможно. В Delphi это делается элементарно.
                                        0
                                        Тут ключевой вопрос не «кто может менять объект», а «когда его могут менять».

                                        В частности, иммутабельный объект всегда потокобезопасен и реентерабелен без дополнительных усилий. В отличии от мутабельных объектов.
                                          +1
                                          Тут есть какой нюанс. Иммутабельность довольно просто 'эмулируется' read only свойствами/инкапсуляцией. То есть — нужно — сделали иммутабельным. Не нужно — сделали обычным. А вот в тех языках, где всё иммутабельное выбора, увы, нет.
                                            0
                                            А вот в тех языках, где всё иммутабельное выбора, увы, нет.

                                            Нужен ли такой выбор программисту, если компилятор потом сам приведет к оптимальному виду?
                                              +1
                                              Таких компиляторов не существует, которые смогут понять, что код, написанный программистом, реализует иммутабельный словарь, и заменит его на гораздо более эффективный обычный мутабельный словарь, проанализирует сценарии конкурентного доступа и, где необходимо, защитит словарь mutex-ом.
                                                –1
                                                Насколько мне известно:
                                                1. Со строками компилятор С# действует подобным способом
                                                2. В функциональных языках на уровне «для программиста» (как это делается в рантайме отдельный вопрос) иммутабельность реализуется путем создания копии, т.е. программисту в принципе нет необходимости реализовывать иммутабельный словарь
                                                  +1
                                                  2. Вероятно, вы не знакомы с проблемой. Можно прочитать здесь, в первом пункте.
                                                  0
                                                  Кстати, вы по-моему путаете иммутабельность с потокобезопасностью… И я тоже про иммутабельный словарь повторил
                                                    0
                                                    Ну так иммутабельный словарь потокобезопасен.
                                                      –1
                                                      Снег — белый, но не всё, что белое — снег
                                            0
                                            Также не совсем очевидны выгоды от иммутабельности. Возможно в каких-то случаях она полезна, сложно сказать.

                                            Иммутабельность полезна в случаях, когда создаётся кусок данных (объект), который используется в нескольких местах и/или в разных потоках. Тогда вероятность того, что такой объект ВНЕЗАПНО поменяется, равна нулю. К слову, иммутабельность легко реализуется на любых ООП-языках (может, и не только ООП) — достаточно не писать сеттеров и не менять поля объекта кроме как в конструкторе. А вот наоборот — "чуть" сложнее.

                                              0
                                              Стандартный вопрос на собеседовании: «как реализовать неизменяемый объект?» и на ответ, данный вами
                                              достаточно не писать сеттеров и не менять поля объекта кроме как в конструкторе
                                              стандартный дополнительный вопрос: «а если я в конструктор передам изменяемый nestedObject? И потом изменю его состояние?». В результате беседы приходим к выводу, что вся иерархия объектов должна быть неизменяемой. И что вручную это сделать накладно, если в языке какой-нибудь Integer или String по своей природе mutable.
                                              P.S. В основном я с вами согласен — неизменяемость полезна при многопоточности и может здорово упростить жизнь. Я лишь хочу подчеркнуть, что гарантии неизменяемости «из коробки» полезны. Особенно если есть четкая грань, что mutable а что нет. Например scala.mutable.Array vs scala.immutable.List — сразу понятно что к чему даже новичку в языке.
                                                –2
                                                > «а если я в конструктор передам изменяемый nestedObject? И потом изменю его состояние?».

                                                То ничего не изменится — наш объект останется иммутабельным (если забыть про рефлексию и подобные трюки). :)
                                                  –1
                                                  а если я в конструктор передам изменяемый nestedObject? И потом изменю его состояние?

                                                  Вы просто не сможете это сделать:


                                                  Error: cannot implicitly convert expression bar of type Bar to immutable(Bar)
                                                    0
                                                    Я придрался к фразе
                                                    иммутабельность легко реализуется на любых ООП-языках (может, и не только ООП) — достаточно не писать сеттеров и не менять поля объекта кроме как в конструкторе
                                                    В вашем примере неизменяемость реализована за счет ключевого слова immutable — такое есть не во всех языках.
                                                    Вот код на java, показывающий идею
                                                    class Compensation {
                                                    	int salary;
                                                    	int yearPremium;
                                                    	public int getSalary() {return salary;}
                                                    	public int getYearPremium() {return yearPremium;}
                                                    }
                                                    
                                                    class Employee {
                                                    	private Compensation compensation;
                                                    
                                                    	public Employee(Compensation compensation) {
                                                    		this.compensation = compensation;
                                                    	}
                                                    
                                                    	public int calculateYearCost() {
                                                    		return compensation.getYearPremium() + 12 * compensation.getSalary();
                                                    	}
                                                    }
                                                    
                                                    @Test
                                                    public void testImmutable() {
                                                    	Compensation offer = new Compensation();
                                                    	offer.yearPremium = 1000;
                                                    	offer.salary = 1000;
                                                    	Employee newcomer = new Employee(offer);
                                                    	offer.yearPremium = 1_000_000;
                                                    	assertEquals(newcomer.calculateYearCost(), 13_000);
                                                    }

                                                    Злобный хакер баг-хантер получит премию, а на собеседовании стоит внимательно слушать вопросы ;-)
                                                0
                                                Главный минус и главный же плюс использования иммутабельности в хорошо знакомых мне ООП языках — сравнение по ссылке говорит изменялась ли сущность, но не говорит, что, возможно, состояние вернулось в начальное после нескольких изменений и никак реагировать на них не нужно.
                                                  0
                                                  Для этого, если мне не изменяет память, существует шаблон Publish-Subscribe, чтобы ООП-парадигма в отдельно взятой реализации не превратилась в Eiffel.
                                                    0

                                                    Помимо самого изменения сущности, есть еще время изменения. Которое всегда меняется. Так что никаких минусов нет.

                                                      0
                                                      Не понял о каком времени речь.
                                                        0

                                                        Значения меняются во времени или нет?

                                                          0
                                                          В каком времени? В реальном или моделируемом?
                                                            –1

                                                            Доверять клиентским изменениям или кэшу никто в здравом уме не будет. Любые изменения должны быть подтверждены эндом (в частности сервером). Т.е. в результате все подтвержденные изменения как минимум логируются.

                                                              +2
                                                              Чем дальше, тем меньше понимаю о чём речь.
                                                                –1

                                                                Компилятор с любого языка не обеспечивает хэширование измененных значений, так как есть ограничение на длину ключа (за лисп не могу сказать). Т.е. вы не можете автоматически превратить иммутабельное значение в ключ и напихать измененных значений под этот ключ.
                                                                Но как тут указали всё "более легко реализуется на любых ООП-языках"
                                                                Почему то никто не рассуждает о мутабельности ключей, которая тоже иногда нужна.

                                                                0
                                                                Как-то вы ВНЕЗАПНО перескочили к безопасности сервера и небезопасности клиента, хотя ничего, НИЧЕГО! Не предвещало этого. Я даже капсить начал, чтобы обозначить, насколько внезапный и неуместный, слово детский понос в метро, был ваш комментарий.
                                                    –1
                                                    Вы упустили один важный момент в сравнении наследования и композиции — наследование оптимизирует память (меньше объектов) и скорость (меньше cpu циклов на создание а потом и уборку объектов). Когда имеется например 10 последовательных переопределений поведения или добавлений нового функционала (для ui-разработки компонентов это распространенная ситуация) то для какого-нибудь списка из тысячи компонентов при использовании композиции будет создано 10 тысяч объектов а при использовании наследования в десять раз меньше — 1 тысяча объектов. А если будет цепочка из 20-ти переопределений или расширений то используя композицию будет создано уже в 20 раз больше объектов и т.д — то есть сколько бы цепочек не городили бы с наследованием количество объектов нисколько не увеличивается в отличие от композиции
                                                      +1
                                                      Это касается только языков, которые не умеют выделять память под композицию объектов как одно целое. Например, в C++ не никакой разницы, делать
                                                      class InputDevice : public Device { ... }
                                                      или
                                                      class InputDevice {
                                                         public: Device device;
                                                      }
                                                        0

                                                        Вы имеете ввиду аллокацию на стеке? А нет ли в с++ оверхеда по памяти на сам объект класса? То есть если внутри класса Device будет еще одно поле


                                                        class Device {
                                                           public: AnotherDevice device;
                                                        }

                                                        А внутри AnotherDevice еще одно поле с инстансом другого класса и т.д, и если будет такая цепочка из тысячи вложенных полей вырастет ли итоговый размер объекта InputDevice в сравнении вариантом когда строим цепочки через наследование или нет?

                                                          0
                                                          С++ аллоцирует память под композицию 1 раз, независимо от того, объект на стеке создан или в куче. В структуре объекта поле public: AnotherDevice device;
                                                          это не указатель, это сам объект AnotherDevice, все его поля. Компилятор знает, с какого смещения начинается вложенный объект и формирует указатели на вложенный объект, когда они нужны, добавлением константы к указателю на объект-композит.
                                                            0
                                                            А в с++ размер объекта будет строго равен сумме размеров объектов его полей или добавится еще небольшой оверхед на какие-то служебные поля? Получается что если есть даже минимальный оверхед на объект в один бит то с ростом цепочки вложенности будет расти и размер главного объекта а с наследованием длина цепочки переопределений на размер объекта не повлияет.
                                                              0
                                                              Сумма полей. К таковым, в данном случае, относятся укзатели на виртуальные функции — тоесть размер всех переменных-членов класса + vtable, а далеехоть так хоть этак определяй InputDevice — результат будет одинаковый.
                                                                +1
                                                                Без виртуальных методов будет строго одинаково.
                                                                Для каждого включенного объекта с вирт. методами будет на 1 указатель больше (vptr).

                                                                Однако, если не наследоваться, виртуальные методы не нужны :D
                                                          0

                                                          Аналог композиций в БД это массивы из кортежей и никто не парится из-за памяти. Это время ушло.

                                                          +2
                                                          У меня есть своя теория на этот счет. В программировании полно народу, которые пришли сюда не потому что им это нравится, а потому что тут бабки платят. Соответственно среди таких полно даже гуманитариев. А гуманитарии не могут в абстракции, так как это по сути уже математика, уравнение в котором неизвестным является сразу все.
                                                          • UFO just landed and posted this here
                                                              –1
                                                              Верстальщик это по сути junior JavaScript developer. Если нет, то верстальщик становится невостребованным на рынке. Гуманитариям приходится плакать, но продолжать жрать кактус. Плач выражается в хейте ООП.
                                                                +1
                                                                Ковырните соседей по офису, запросто может обнаружится, что тот офигенный спец, который строит офигенный продукт, в девичестве имеет красный диплом по, скажем, экономике.
                                                                  –2
                                                                  Не встречал таких. Физиков, математиков и конструкторов — встречал, экономистов — максимум тестеры или верстальщики (без особого JS), а вот программистов, не умеющих в «ться», встречаю постоянно.
                                                                  • UFO just landed and posted this here
                                                                    –2
                                                                    Видел, правда ещё не разобрался к какому классу относятся эти товарищи.При мне работали Барышни-погромистки в великой желтой программе, все сплошняком гуманитарии. И да, они таки писали.
                                                                    0
                                                                    А вы этой теорией за чей лагерь? «За ООП» или «против ООП»?)
                                                                      +1
                                                                      Я за то, что все хорошо в меру.
                                                                      Как то раз делал тестовое задание при приеме на работу. Нужно было написать демона, который пингует адрес и шлет репорты, если пинг не проходит. Там кода 10 строчек. Ну я и написал просто 10 строчек. Понятно, что для демонстрации скиллов этого не достаточно и я прикрутил демону ООПешную возможность прикручивать разные способы отправки репортов. Но все равно первые же два вопроса были «Почему не весь код ООП?», «Почему не использовали фреймворков?». Прикручивать какойнибудь симфони ради 10 строчек кода, да еще и демону?.. На работу меня тогда не взяли…
                                                                        0

                                                                        И хорошо что не взяли, Вам же лучше, вы просто не застряли в болоте. Когда парадигма, — самоцель и когда годами размышляют над иерархией классов и тремя шаблонами, или над мутабельностью/иммутабельностью, — ничего хорошего из этого не выходит.


                                                                        Вообще это такой суровый ынтырпрайз, не написал 2000 строк и всё через ООП вместо десяти которыми можно решить задачу. При этом перед тем как писать код ещё и UML диаграммы все нарисовать от use-case и заканчивая deployment. Это как дрескод нарушуть и в плавках на банкет явиться.

                                                                        • UFO just landed and posted this here
                                                                      0
                                                                      1. ООП смешивает данные и действия над ними. Это плохо

                                                                      Думаю, Вы не совсем правильно поняли этот аргумент. Плохо когда пытаются абсолютно всё представлять объектами, искусственно симулируя наборы данных и действий там, где их нет: число 3 это не объект, равно как и функция sum(a,b int) не является частью/методом какого-то объекта. Всё хорошо в меру, где-то используемые кодом абстракции действительно лучше представлять в виде объектов, но требование чтобы объектом было абсолютно всё добавляет accidental complexity на пустом месте.


                                                                      1. Наследование закрепощает программу, делает трудным внесение изменений

                                                                      Настоящее отношение is a между двумя разными абстракциями в реальном коде встречается крайне редко. А когда его пытаются насильно внедрить ради формального следования DRY случается беда. Поэтому наследование оказалось далеко не таким полезным инструментом, как его нам пытались п(р)одать евангелисты ООП. Из-за этого было написано очень много кода, которое использовало наследование слишком интенсивно и почти всегда не к месту, что и вызвало проблемы. Да, инструмент не виноват, но конкретно этот оказался настолько слабо применимым и проблемным, что ему место на дальней полке, и, по хорошему, разрешать им пользоваться можно только очень квалифицированным разработчикам.


                                                                      1. Методология ООП изначально ошибочна
                                                                        Абсолютно необоснованный аргумент. ООП создавалось для того, чтобы моделировать своеобразный виртуальный мир, состоящий из объектов, как и наш мир.

                                                                      Наш мир не состоит из объектов. Это просто один из способов смотреть на мир, и способ довольно корявый и ограниченный. Иными словами эта абстракция не очень корректна, поэтому попытки применять её часто дают не очень хорошие результаты. А поскольку эта идея подаётся как основание ООП… Ничего не имею против ООП, но вот этот бред про "мир состоит из объектов" надо забыть как можно быстрее, он больше вредит ООП чем помогает.


                                                                      1. Но даже миллионы мух не убедят нас, что навоз — это вкусно
                                                                        Мол, массы в большинстве своём глупы (всё же я не думаю, что это относится и к программистам), бегают по «модным шмоткам» и восхищаются ими.

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

                                                                        0
                                                                        Плохо когда пытаются абсолютно всё представлять объектами, искусственно симулируя наборы данных и действий там, где их нет

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

                                                                        Тут даже из вашего примера следует, что проблема не в ООП, а в том что у когото DRY головного мозга. До меня однажды докапались, почему у меня дважды написаны 4 одинаковые строчки, мол я должен вынести все в функцию. Только вот каждая из этих строчек уже была функцией, но с разными параметрами. Вынесение в функцию вылилось бы в усложнение кода и даже в увеличение количества строк. Но человеку было все равно, донт репит ёрселф и все тут.
                                                                          +1
                                                                          Наследование — это самый мощный инструмент ООП. По-сути, без наследования (и связанного с ним полиморфизма) ООП особого смысла не имеет, ибо все остальное можно смоделировать, назвав процедуры удобным тебе образом.

                                                                          Тут надо отойти в сторонку и сказать, зачем нужны ООП/ФП/etc. Основная цель любой методологии и любого нормального языка программирования — упростить решение задач. Определенных задач, разумеется, потому что универсального подхода пока никто не придумал. В программировании простота решения коррелирует с количеством кода, которое ты должен написать в прикладной программе. Пишешь меньше кода — тратишь меньше времени, упрощаешь поддержку продукта. Именно с этой точки зрения надо смотреть на языки программирования. Категории «труъ» и «не-труъ» интересны только как индикаторы достижения цели.

                                                                          Так вот, для упрощения работы программиста в незапамятные времена были придуманы библиотеки процедур и вообще структурное программирование. Сейчас апологеты композиции (composition over inheritance) говорят, что вам достаточно скомбинировать библиотечные функции нужным образом чтобы получить требуемое сложное поведение. Это так, но таковая композиция сама по себе является сложной сущностью. Аналог такой сущности — стойка с сетевым оборудованием. Все компоненты в стойке стандартны, но конкретная конфигурация стойки — нет.

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

                                                                          Класс в ООП — это по сути композиция функций, в которой можно подменять отдельные компоненты. Для этого там существует наследование и полиморфизм. Все просто.

                                                                            +4
                                                                            По-сути, без наследования (и связанного с ним полиморфизма) ООП особого смысла не имеет

                                                                            Полиморфизм — безусловно правильная штука. Только вот к наследованию его привязали именно в ООП, а вообще полиморфизм отлично существует и без наследования. В качестве примера посмотрите на интерфейсы в Go или просто почитайте статью в википедии про варианты полиморфизма.

                                                                              0
                                                                              Почитаю, спасибо, но речь же шла не о преимуществах Go перед другими языками. Речь о том, что, имея поддержку ООП в своем повседневном языке, человек ей не пользуется. По надуманным причинам.
                                                                                0

                                                                                Ещё точнее — речь шла о наследовании как инструменте, а не о полиморфизме. Если наследование применяется не как инструмент для создания реальной иерархии, DRY и моделирования отношений is a между сущностями предметной области, а просто как синтаксическая форма записи необходимая для использования полиморфизма в конкретном языке (т.е. речь о создании абстрактных классов нужных исключительно для декларирования набора поддерживаемых методов, от которых потом выполняется множественное наследование не вкладывая в это никакого смысла кроме "я поддерживаю этот набор методов и подразумевающуюся с ним семантику") — в этом ничего плохого нет (как впрочем в этом нет и настоящего наследования чего либо).

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

                                                                              Если вы можете построить из компонентов объект — это ООП. Класс это статическая композиция. Да инжекция возможна, но не изменение числа методов. И это главная засада классов.

                                                                              +7
                                                                              Наш мир не состоит из объектов.

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

                                                                                В примере с яблоком никакого нового объекта не создается, иначе достаточно было бы потыкать в яблоко зубочисткой, чтобы накормить всех голодающих в Африке.
                                                                                  +6
                                                                                  Кажется, у вас детектор сарказма сломался…
                                                                                    0
                                                                                    Ну так тэга то не было, а по косвенным признакам не сработал — бывает…
                                                                                    0
                                                                                    Сарказм и отсылка к парадоксу Тесея
                                                                                  –1
                                                                                  число 3 это не объект, равно как и функция sum(a,b int) не является частью/методом какого-то объекта.


                                                                                  А что такое число 3? Это «данные»? А что такое «данные»? Как «данные» могут существовать без интерпретатора?

                                                                                  Если я напишу вам сообщение «На столе три яблока», или «На столе 3 яблока», или «На столе III яблока», скорее всего, во всех трех случая вы представите себе подобное:


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

                                                                                  Объект — упаковка для смысла. Методы объекта — способ понимания смысла.
                                                                                  "Код на Smalltalk"
                                                                                  
                                                                                  tableWithThreeApples := me interpret: 'На столе три яблока'
                                                                                  
                                                                                  apple := tableWithThreeApples takeOneApple.
                                                                                  apple isFruit. "true"
                                                                                  
                                                                                  numberOfApples := tableWithThreeApple howManyApplesDoYouHave.
                                                                                  numberOfApples = 2. "true"
                                                                                  


                                                                                  Но если интерпретаторы разные, то и объекты, а значит и смысл могут быть разными. Вполне возможен такой поворот событий:
                                                                                  tableWithThreeApples := appleFanboy interpret: 'На столе три яблока'
                                                                                  
                                                                                  apple := tableWithThreeApples takeOneApple.
                                                                                  apple isFruit. "false"
                                                                                  apple isComputer. "true"
                                                                                  
                                                                                  numberOfApples := tableWithThreeApple howManyApplesDoYouHave.
                                                                                  numberOfApples = 2. "true"
                                                                                  


                                                                                  Возвращаясь к числу 3, невозможно понять его смысл, пока нет объекта, который этот смысл упаковывает, и методов, которые этот смысл поясняют.
                                                                                    +2

                                                                                    Читая, хотелось аплодировать стоя — совершенно волшебная демагогия.


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

                                                                                    Расскажите это на уроке математики.

                                                                                      0
                                                                                      Ребенку, который не знает чисел и основ математики, будет непонятно число 3. Для такого ребенка в числе 3 нет смысла. Он не сможет интерпретировать сообщение «3 + 2», потому что не знает смысл объектов «3» и «2» и доступных у них методов вроде "+" и "-".

                                                                                      Хоть вы и не ответили на мои вопросы из прошлого сообщения, я все рано задам еще. Вы действительно думаете, что числа — это что-то не имеющее смысла? А если смысл всё-таки есть, то разве методы (операции, возможности) вроде "+", "-", "*", "/" существуют не для пояснения смысла, заключенного в число?
                                                                                        –1
                                                                                        А если смысл всё-таки есть, то разве методы (операции, возможности) вроде "+", "-", "*", "/" существуют не для пояснения смысла, заключенного в число?

                                                                                        Только вы все напутали. +-*/ — это как раз объекты, а вот у них уже в свою очередь есть метод apply, который принимает в качестве аргументов числа: plus.apply(1,2)

                                                                                          0
                                                                                          Вопрос трактовки. Формально математические операции — это функции, а не объкты. Объекты имеют состояние, функции — нет. то есть не plus.apply(1,2), а plus(1,2). Или this = 1; plus(this, 2), для чего есть запись 1.plus(2) :)
                                                                                            –1
                                                                                            Объекты имеют состояние

                                                                                            Могут иметь. А могут — не иметь.


                                                                                            Или this = 1; plus(this, 2), для чего есть запись 1.plus(2) :)

                                                                                            Тогда у каждого числа свой plus, что семантически неверно, операция-то только одна.

                                                                                              0
                                                                                              Тогда у каждого числа свой plus

                                                                                              С чего бы? Методы как бы общие для всего класса чисел.


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


                                                                                              Простейший такой способ — каждое число как объект. Другой способ — операция как объект.


                                                                                              У каждого способа своя сфера применения. Первый случай больше подходит для создания собственных алгебр, второй — для написания парсеров, интерпретаторов, компиляторов или проведения символьных вычислений.

                                                                                                –1
                                                                                                С чего бы? Методы как бы общие для всего класса чисел.

                                                                                                Нет, в ООП вообще у каждого объекта свой метод. Просто часто они совпадают.


                                                                                                Первый случай больше подходит для создания собственных алгебр

                                                                                                Первый вообще ни в каких случаях не подходит.

                                                                                                  +1
                                                                                                  В ООП вообще нет методов, с одной стороны, с другой, в тех реализациях, где они есть, чаще всего все методы одного класса делятся друг с другом, только значение указателя/ссылки типа this/self разное при вызове метода объекта, а код один.
                                                                                                    –1
                                                                                                    В ООП вообще нет методов, с одной стороны

                                                                                                    Нет, методы то везде есть, они только могут называться по-другому (сообщения, например).


                                                                                                    чаще всего все методы одного класса

                                                                                                    Методы не у класса, а у объекта. ООП ортогонально классам (на то оно и объектно-ориентированное, а не классо-ориентированное :)).
                                                                                                    ООП с классами — это лишь один из вариантов.

                                                                                                      +1
                                                                                                      Скорее методы очень частный случай сообщений, и это лишь один из вариантов :)
                                                                                                        0
                                                                                                        Скорее методы очень частный случай сообщений

                                                                                                        Это не частный случай, а просто разные названия одного и того же :)

                                                                                                          0
                                                                                                          Есть всё-таки разница между посылкой сообщения объекту и вызовом его метода. Как правило для вызова метода мы должны точно знать и соблюдать его сигнатуру. Ошибки в вызове метода обычно приводят к рантайм, а то и компайлтайм ошибкам. Непонятные сообщения же объект просто игнорирует.

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

                                                                                                            И наоборот. Именно по-этому это и есть одно и то же.

                                                                                                        0

                                                                                                        Везде есть функции. А вот диспетчеризации их вызовов могут быть разные. Это может быть прямой вызов конкретной функции (в том числе невиртуальные методы). Может быть выбор наиболее подходящей функции в зависимости от типа объекта (виртуальный метод), может быть выбор на основе всей сигнатуры (множественная диспетчеризация). Посылка сообщения — это вызов функции приёма сообщения с параметрами: объкт и сообщение. А как она диспетчеризируется зависит от языка.

                                                                                                      0
                                                                                                      Хорошо, «уговорили», у каждого объекта свой метод.

                                                                                                      Но чем это плохо? Почему одной операции не может соответствовать целый класс методов?
                                                                                                        0
                                                                                                        Почему одной операции не может соответствовать целый класс методов?

                                                                                                        А что это значит с точки зрения семантики? Мы же моделируем предметную область, так?

                                                                                                          +1
                                                                                                          У каждого объекта реального мира своя реакция на события внешнего мира. Они могут быть одинаковы, например описываться одной формулой, но они принадлежат объекту.
                                                                                                            0
                                                                                                            Они могут быть одинаковы, например описываться одной формулой, но они принадлежат объекту.

                                                                                                            Ну так операции над числами не принадлежат числам. Они не являются ни событиями, ни реакцией на эти события.

                                                                                                              0
                                                                                                              Это лишь условность. Захотим чтобы принадлежали — будут принадлежать.
                                                                                                                0
                                                                                                                Это лишь условность. Захотим чтобы принадлежали — будут принадлежать.

                                                                                                                Так я же и спрашиваю — с точки зрения семантики предметной области это какой смысл имеет?
                                                                                                                Так-то мы можем куда угодно засунуть какой угодно метод, например почему бы арифметическим операциям не быть методами уток? Или плюс — а утки, а умножение — у жирафа?
                                                                                                                Надо что-то умножить? Отлично! Создаете жирафа с нужной шеей при помощи фабрики жирафов и умножаете! :)
                                                                                                                Бессмысленно? Не более, чем иметь операцию плюс у числа.

                                                                                                                  0

                                                                                                                  Простите, а чем вас "сложи себя вот с этим числом и сообщи результат" в качестве семантики не устраивает-то?

                                                                                                                    –1
                                                                                                                    а чем вас "сложи себя вот с этим числом и сообщи результат"

                                                                                                                    Тем, что числа не умеют складывать :)
                                                                                                                    Числа являются объектами арифметических операций, а не субъектами.

                                                                                                                      +2
                                                                                                                      Умеют они себя складывать или нет — зависит только от построенной модели.
                                                                                                                        –2
                                                                                                                        Умеют они себя складывать или нет — зависит только от построенной модели.

                                                                                                                        Так я ж говорю — ради бога, можете хоть жирафами умножать. Только это шизофрения, а так-то — норм все.

                                                                                                                    0
                                                                                                                    Если подразумевать под числом точку на прямой, то сложение это сдвиг заданной точки на заданный вектор. Это больше подходит для оператора '+=', но тем не менее смысл есть.
                                                                                                                  0
                                                                                                                  Зависит от того как моделируем. Сложение можно представить как сообщение числу «я хочу увеличить тебя на вот это число», а результат как «да, я себя увеличил, теперь у меня новое состояние».
                                                                                                                    0
                                                                                                                    Сложение можно представить как сообщение числу «я хочу увеличить тебя на вот это число», а результат как «да, я себя увеличил, теперь у меня новое состояние».

                                                                                                                    "Состояние у числа" — это уже совсем что-то шизофреническое, уж извините.

                                                                                                                      +2
                                                                                                                      Только в рамках классической математики может выглядеть странно. Модель программы вовсе не должна следовать общепринятым математическим и прочим моделям.
                                                                                                                        –1
                                                                                                                        Только в рамках классической математики может выглядеть странно.

                                                                                                                        Замечательно, я не против того, чтобы кто-то сделал свою неклассическую математику, но только тогда ваши числа — не числа.
                                                                                                                        А то, что для не-чисел может быть все не так как для чисел — это, конечно, верно.


                                                                                                                        Модель программы вовсе не должна следовать общепринятым математическим и прочим моделям.

                                                                                                                        Да, модель не обязана следовать чему бы то ни было, но обычно такая модель — говно, а не модель.

                                                                                                                          +1
                                                                                                                          Так давно привыкли использовать модели, противоречащие математике.

                                                                                                                          Попробуйте отказаться от такого:
                                                                                                                          i=i+1
                                                                                                                            0
                                                                                                                            Попробуйте отказаться от такого:

                                                                                                                            1. зачем?
                                                                                                                            2. что тут чему противоречит?
                                                                                                                              0
                                                                                                                              зачем?

                                                                                                                              Потому что такая запись противоречит общепринятым математическим моделям, где изменение значения принято обозначать другой переменной (Ti, Ti+1, Ti+2 и т.д., вместо T, T, T).
                                                                                                                              что тут чему противоречит?
                                                                                                                              из i=i+1 следует противоречие 0=1
                                                                                                                                –1
                                                                                                                                Потому что такая запись противоречит общепринятым математическим моделям

                                                                                                                                Почему противоречит? Нет.


                                                                                                                                из i=i+1 следует противоречие 0=1

                                                                                                                                Нет, не следует, потому что = — это присваивание, а не сравнение.

                                                                                                                                  +1
                                                                                                                                  Но обозначается тем же символом. Выражаясь вашими словами — шизофрения это получается.
                                                                                                                                    0
                                                                                                                                    Но обозначается тем же символом.

                                                                                                                                    Какая разница, каким символом оно обозначается? Важно не как вы что обозначаете, а какой эти символы несут смысл.
                                                                                                                                    Шизофрения — это когда у вас что-то, что по смыслу должно быть числом, не ведет себя как число.
                                                                                                                                    Обозначать же вы можете что угодно как угодно, и то, что в разных языках одни и те же вещи могут обозначаться по-разному (а формальный язык ZFC и язык какого-нибудь ЯП — это разные языки) не является чем-то странным.

                                                                                                                                    0
                                                                                                                                    Присваиваний в математике нет, есть введение обозначений (аналог let в функциональных языках).

                                                                                                                                    Значение переменной не меняется. Иначе это не переменная, а функция, либо последовательность.
                                                                                                                                      0
                                                                                                                                      Вместо присваиваний в математике есть введение обозначений (аналог let в функциональных языках).

                                                                                                                                      И что дальше? Вещи-то это разные. Где противоречие?


                                                                                                                                      Значение переменной не меняется.

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

                                                                                                                                        0
                                                                                                                                        Я просто вас процитирую
                                                                                                                                        Модель программы вовсе не должна следовать общепринятым математическим и прочим моделям.
                                                                                                                                        Да, модель не обязана следовать чему бы то ни было, но обычно такая модель — говно, а не модель.

                                                                                                                                        В какой математике вы видели общепринятую модель с изменяющимися во времени переменными?
                                                                                                                                          0
                                                                                                                                          В какой математике вы видели общепринятую модель с изменяющимися во времени переменными?

                                                                                                                                          Да в любой, которая описывает операционную семантику императивного языка.

                                                                                                                                            0
                                                                                                                                            А конкретнее? Чтобы была построена формальная система? Я знаю только одну модель, описывающую эволюцию переменных в памяти — машина тьюринга.
                                                                                                                                              0
                                                                                                                                              А конкретнее? Чтобы была построена формальная система?

                                                                                                                                              Речь о семантике для языка.
                                                                                                                                              https://ru.wikipedia.org/wiki/%D0%A1%D0%B5%D0%BC%D0%B0%D0%BD%D1%82%D0%B8%D0%BA%D0%B0_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)

                                                                                                                                                0
                                                                                                                                                Вы читали текст по ссылке? Он не даёт требуемых примеров:
                                                                                                                                                В качестве инструментов построения таких моделей могут использоваться различные средства, например, математическая логика, λ-исчисление, теория множеств, теория категорий, теория моделей, универсальная алгебра.

                                                                                                                                                И где в λ-исчислении (и т.д. по списку) модель императивного языка?
                                                                                                                                                  0

                                                                                                                                                  Вы б дальше текст по ссылке изволили прочесть, там где виды семантик. После этого ваши вопросы должны отпасть. В частности, нас особенно операционные интересуют:
                                                                                                                                                  https://en.wikipedia.org/wiki/Operational_semantics

                                                                                                                                          0
                                                                                                                                          Так «число ведёт себя» в математике и программировании совершенно разные вещи и вместе, и по отдельности «число», «ведёт» и «себя».
                                                                                                                                            –1

                                                                                                                                            И? :)

                                                                                                                                0
                                                                                                                                Хорошая модель строится не по совокупности всех доступных знаний человечества, а по знаниям предметной области в данном в задаче контексте. Пример, спроси у бухгалтера что такое налоговая ставка, он скажет что это число, которое..., сейчас по умолчанию оно равно N. А потом скажет, что в некоторых случаях это число увеличивается до M.
                                                                                                                                  –1
                                                                                                                                  Пример, спроси у бухгалтера что такое налоговая ставка, он скажет что это число, которое...

                                                                                                                                  Не важно, что он скажет, важно, что он будет иметь ввиду. Мы ведь люди и общаемся на ЕЯ. Если вы будете такие слова бухгалтера буквально понимать, у вас, очевидно, проблемы.
                                                                                                                                  В данном конкретном случае — я не думаю, что вы будете для decimal делать метод "увеличить_ставку".

                                                                                                                                    0
                                                                                                                                    Для Decimal наверное не буду, а вот для TaxRate extends Decimal сделаю метод «increase» именно для поддержки ЕЯ в предметно области
                                                                                                                                      0

                                                                                                                                      Но ведь это будет метод именно TaxRate, а не метод "числа" :)
                                                                                                                                      Видите, вы верно поняли бухгалтера (не смотря на то, что "формально" он вроде как дичь сказал) и все в порядке.

                                                                                                                                        0
                                                                                                                                        TaxRate является числом. Грубо, есть натуральные числа, целые, дробные, десятичные и есть налоговые ставки. Ну а если бухгалтер про каждое число в программе будет так говорить то добавляю метод в Decimal, ЕЯ же.
                                                                                                                                          0
                                                                                                                                          Как по мне — композиция тут больше подходит. А вообще спор у вас странный, я потерял мысль( Можете, пожалуйста, прояснить предмет?
                                                                                                                                            0
                                                                                                                                            Для демонстрации того, что число может являться объектом со своим состоянием и методами, его изменяющими, наследование подходит лучше :) Собственно спор о том, является ли шизофренией представление числа в виде объекта, в том числе мутабельного.
                                                                                                                                              0
                                                                                                                                              А какая разница? Вот допустим, что не является. Или допустим, что является. Если одна из точек зрения верна, то следствие...?
                                                                                                                                                0
                                                                                                                                                Если моя точка зрения неверна, то можно ставить диагнозы по коду. В частности авторам всех языков, где всё объект или хотя бы есть объекты, представляющие числа. Ну и держаться от такого кода подальше, чтобы не заразиться шизофреническим мышлением :)
                                                                                                                                                  0
                                                                                                                                                  Ну а до того? Если подняться на уровень выше. Ну вот допустим ваш оппонент погарячился и не совсем так выразился и именно этот пример не так важен, но тот, изначальный родник, который привел нас к этой реке — о чем он?
                                                                                                                                                    0
                                                                                                                                                    Я так понимаю, речь про то, что Druu имеет ввиду числа как математические числа. То есть вечные константные инстансы, на которые ссылаются все математики мира. Тогда «изменение числа» это запись вида «2 := 10», что действительно странно.
                                                                                                                                                      0
                                                                                                                                                      Я так понимаю, речь про то, что Druu имеет ввиду числа как математические числа.

                                                                                                                                                      Правильно. Если же ваши числа — не математические, то это будет указано либо в семантике языка, либо будет что-то в виде TaxeRate из примера выше.

                                                                                                                                              0
                                                                                                                                              А почему для этой задачи не использовать персептрон? Он лучше, на ваш взгляд, справится?

                                                                                                                                              Угу, но если я задам вопрос: "вы добавили метод к decimal?", то вы ведь ответите: "нет!", правильно? :)

                                                                                                                                      • UFO just landed and posted this here
                                                                                                                                0

                                                                                                                                Более того, предлагаю подумать над такой темой, как сложение разных типов: 1 + 1.1 — метод какого класса должен быть вызван: левого операнда или правого? А если это должна быть внешняя функция, то как быть в случае сокрытия внутреннего состояния операндов? Можно попробовать воспользоваться более широкой областью видимости, но как быть в случае, если каждый класс раз разрабатывается совершенно разными людьми? Кто из них должен обеспечить совместимость с другими типами?

                                                                                                                0
                                                                                                                Вы действительно думаете, что числа — это что-то не имеющее смысла?

                                                                                                                Нет, я такого не говорил. Я говорил, что число — это не объект. Смысл, как и методы, к числу 3 можно прилепить самые разнообразные (это вопрос упомянутой Вами интерпретации). А можно этого и не делать. Число 3 от такого отношения к нему не испортится, не сломается, не обидится, и не станет менее полезным. Это и отличает данные от объектов: у объекта есть "смысл"/интерпретация, пользуясь Вашей терминологией, а у данных этого нет. Да, к данным это можно добавить, и мы получим объект. Но делать это вовсе не обязательно.


                                                                                                                А если смысл всё-таки есть, то разве методы (операции, возможности) вроде "+", "-", "*", "/" существуют не для пояснения смысла, заключенного в число?

                                                                                                                В этом-то и проблема. Пока это число 3, это просто данные, и мы можем наделять их любым смыслом, что позволяет интерпретировать и использовать их как угодно. Как только число 3 превращают в объект, к нему гвоздями прибивают какой-то один смысл, и привязанный к этому смыслу набор методов. Для такого отношения нет никаких оснований (кроме пуризма "всё есть объект"), оно ограничивает наши возможности по интерпретированию числа 3 каким-то иным образом (как код символа, например, к которому методы вычитания и умножения не очень-то лепятся), а так же усложняет, замедляет и делает хуже читаемыми программы, которым тупо нужно обычное число 3.

                                                                                                                  0
                                                                                                                  Как только число 3 превращают в объект, к нему гвоздями прибивают какой-то один смысл

                                                                                                                  оно ограничивает наши возможности по интерпретированию числа 3 каким-то иным образом


                                                                                                                  Вам ничего не мешает добавлять любой смысл к объекту. Если в вашей ментальной модели число может быть кодом символа, отобразите это в числе:
                                                                                                                  charCode := 3 asCharCode.
                                                                                                                  charCode + 1. "Instance of CharCode didNotUnderstand #+"
                                                                                                                  


                                                                                                                  Это и отличает данные от объектов: у объекта есть «смысл»/интерпретация, пользуясь Вашей терминологией, а у данных этого нет.

                                                                                                                  Пока это число 3, это просто данные, и мы можем наделять их любым смыслом


                                                                                                                  То есть данные — это все-таки что-то, что не имеет никакого смысла? Если число «3» и строка «лето» являются данными, значит ли это, что они по-сути равны как друг другу, так и абстрактному «ничего»?
                                                                                                              0
                                                                                                              Начали за здравие, закончили за упокой.

                                                                                                              Из наличия собственного смысла у «трех яблок» никак не следует отсутствие собственного смысла у числа «3».
                                                                                                                0
                                                                                                                Конечно у числа есть собственный смысл, я это не отрицал. Я пытался донести идею о том, что числа — это не «данные», числа — это представление определенного смысла. А компактное представление смысла с возможностью исследовать и понимать смысл через использование доступных методов (операций, возможностей) — это объект.

                                                                                                                Предлагаю отвлечься от программирования и подумать о том, как объяснить смысл чисел, например, дельфину.
                                                                                                                  0
                                                                                                                  Числа — данные, объекты — данные и методы их преобразования. Смыслом, как конкретным, так и абстрактным, и числа, и объекты наделяет человек. Дельфины вроде тоже что-то могут. :)
                                                                                                                    0
                                                                                                                    В первом сообщении я задавался вопросом, на который пока что никто не ответил :(
                                                                                                                    А что такое «данные»? Как «данные» могут существовать без интерпретатора?


                                                                                                                    Смыслом, как конкретным, так и абстрактным, и числа, и объекты наделяет человек.

                                                                                                                    Как сделать так, чтобы можно было передать смысл одного и того же объекта без искажений?
                                                                                                                      0
                                                                                                                      Как сделать так, чтобы можно было передать смысл одного и того же объекта без искажений?

                                                                                                                      Записать его определение.

                                                                                                                        0
                                                                                                                        В общем случае задача передачи смысла без искажений не имеет решения :( Каждый субъект передачи может иметь свои интерпретации смысла одних и тех же данных. Можно стремиться к тому, чтобы уменьшить различия, но полностью их устранить вряд ли получится.

                                                                                                                        С другой стороны, не всегда участников передачи интересует полное понимание смысла, достаточно чтобы соблюдались «правила игры».
                                                                                                                      –2
                                                                                                                      А компактное представление смысла с возможностью исследовать и понимать смысл через использование доступных методов (операций, возможностей) — это объект.

                                                                                                                      У натурального числа только два доступных метода — это next() и isZero()

                                                                                                                • UFO just landed and posted this here
                                                                                                                  +1
                                                                                                                  Что характерно, например, в разработке веб-фронтенда такие хейтеры ООП спокойно используют HTML DOM и не жалуются, что это не кошерно. Возможно, даже не обращают внимание на факт соприкосновения с объектами.
                                                                                                                  Автор поднял правильную тему, и в правильном ключе. Спасибо.
                                                                                                                    +1
                                                                                                                    Я, например, жалуюсь. DOM, как и HTML — то еще… чудо. HTML то нарушает еще одну известную парадигму, смешивая код (js) с интерфейсом (всё остальное). Но, другого просто нет, увы.
                                                                                                                      +3
                                                                                                                      А вы не смешивайте, вот и все.
                                                                                                                    +2
                                                                                                                    По моим впечатлениям, самые полярные и непримиримые мнения по функциональщине.
                                                                                                                      0
                                                                                                                      Плюсую, про ООП, кмк, все давно смирились с неизбежным
                                                                                                                        –1
                                                                                                                        КМК эти мнения ничего не значат, функциональщина это чистый матан, кто с матаном не дружит, тот и функциональщину не осилит, процедуры и ООП понять проще, уровень абстракции меньше.
                                                                                                                          +1
                                                                                                                          По моим впечатлениям, самые полярные и непримиримые мнения по функциональщине.

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

                                                                                                                          Другая проблема, что сейчас много людей говнокодят на JS в процедурном стиле с элементами ФП и топят, что они — функциональщики, потому что отказались от классов.
                                                                                                                          0
                                                                                                                          ООП отличная концепция, но она упирается в то, что пытаясь натянуть ее на возможности современных компьютеров приходится жертвовать чистотой идей. На этих стыках возникают множественные вопросы и бесконечные холиворы. Например внедрение функциональщины обусловлено лучшей работой в многопоточной среде, при том, что академическим принципам архитекуры должно быть глубоко фиолетово до решения вопросов коммерчески выгодной утилизации железа.
                                                                                                                          • UFO just landed and posted this here
                                                                                                                          • UFO just landed and posted this here
                                                                                                                              +1
                                                                                                                              Я не автор, но отношусь к этому сугубо отрицательно. Говорят, множественное наследование сложно, потому что может возникнуть «deadly diamond of death», но эту проблему можно элементарно решить на уровне компилятора. Если в классе возникает проблема неоднозначности выбора метода, то нужно заставить разработчика явно реализовать этот метод. Вот и все, вроде.
                                                                                                                                0

                                                                                                                                А какую проблему по вашему должно решать множественное наследование? От обычного-то обычно предлагается отказаться в пользу композиции, про множественное я и молчу. Если у вас объект и швец, и жнец, и игрец, то это уже полное нарушение SRP.

                                                                                                                                  0
                                                                                                                                  Представлять одну сущность с разных сторон. Яблоко, например, и фрукт, и шарообразное тело. Или квадрат — и ромб, и прямоугольник )))
                                                                                                                                    0
                                                                                                                                    Нет, примеров из реальности я могу привести. А вот примера из программистской жизни — не очень. Пару раз когда подобное требовалось это было вызвано дико кривой архитектурой.

                                                                                                                                    И да, ничто не мешает иметь интерфейсы Ромб и Прямоугольник.

                                                                                                                                    Наследовать интерфейсы — хорошо. Наследовать реализацию — не очень. Множественно наследовать реализацию — вообще страх.
                                                                                                                                      +1
                                                                                                                                      И да, ничто не мешает иметь интерфейсы Ромб и Прямоугольник.
                                                                                                                                      Но ведь это не поведение. Вот интерфейс ИмеетПлощать с методом ПосчитатьПлощадь — имеет смысл. Или «РисуемаяФигура» с методом «Нарисовать(холст)» Какой смысл вообще в «Ромбах» и «Прямоугольниках»?
                                                                                                                                        0
                                                                                                                                        Декларация того, что данный объект ведёт себя как ромб или прямоугольник, хотя вообще ими не является. Правда с трудом представляю, что бы это значило:)
                                                                                                                                          0
                                                                                                                                          Я лично рассматриваю интерфейс не как поведение, а как часть сущности. Например интерфейс IEnumerator — что-то, что умеет перечислять. Это не поведение, это существительное. Так же и ромб, и прямоугольник — это сущность, которая с некоторой точки зрения (i.e. при касте) является ромбом или прямоугольником.

                                                                                                                                          Поведение это трейты. Похоже не интерфейсы, но немного другое все-таки. У них и названия другие. Интерфейсы — это IEnumrator, IList, ICollection… Трейты — Display/Debug/Clone/Copy/…
                                                                                                                                            0
                                                                                                                                            что-то, что умеет перечислять. Это не поведение, это существительное
                                                                                                                                            Сначала говорите «умеет перечислять», а потом «существительное».

                                                                                                                                            Конечно, названия у них существительные, но суть — поведенческая. ICollection/IList — содержит элементы и предоставляет определенное поведение. Коллекция вот, к примеру — имеет поведение добавления, удаления и получения элемента. Всё, что коллекция — должно иметь эти поведения. Понимаете о чем я?

                                                                                                                                            Трейты — это вообще что-то из процедурного программирования. «Добавить такую фукциональность». Ну то есть интерфейс говорит «инстанс может содержать и работать с элементами», а трейт говорит: «добавь ка именно такую процедуру».
                                                                                                                                              0
                                                                                                                                              Не вижу смысла спорить об определениях. Суть не меняется, наследование реализации — признанный антипаттерн в большинстве случаев. Один из редких сценариев где это нужно — GUI, тут я не спорю. Множественное наследование куда злее. Его выкинули из кучи языков во время проектирования не из-за религиозных соображений или потому что кто-то не осилил бросать ошибку компиляции если метод неоднозначен.
                                                                                                                                                +2
                                                                                                                                                Его выкинули из кучи языков во время проектирования не из-за религиозных соображений
                                                                                                                                                А почему?
                                                                                                                                                  0
                                                                                                                                                  Ну например поэтому.
                                                                                                                                                    0
                                                                                                                                                    Там только религиозные соображения.
                                                                                                                                                      0
                                                                                                                                                      Multiple implementation inheritance injects a lot of complexity into the implementation. This complexity impacts casting, layout, dispatch, field access, serialization, identity comparisons, verifiability, reflection, generics, and probably lots of other places.

                                                                                                                                                      Это религиозные соображения?
                                                                                                                                                        0
                                                                                                                                                        Да, ничего конкретного нет.
                                                                                                                                                        Какие проблемы с casting?
                                                                                                                                                          0
                                                                                                                                                          Генерики вон тоже сложно, в Go их нет, однако они есть а Java, C#,…
                                                                                                                                                            0
                                                                                                                                                            Не знаю, я вопрос на таком уровне не изучал. Если бы я покопался в компиляторе пару лет и потом мне дали бы эту тему на ресерч на месяцок, я смог бы дать ответ.

                                                                                                                                                            Не вижу повода не верить человеку, который эту экспертизу провел.

                                                                                                                                                            Собственно с чего началась эта ветка:

                                                                                                                                                            Говорят, множественное наследование сложно, потому что может возникнуть «deadly diamond of death», но эту проблему можно элементарно решить на уровне компилятора.

                                                                                                                                                            1. Нет никаких доказательств, что это просто. Зато социальное доказательство обратного — есть
                                                                                                                                                            2. У людей нет задачи сделать идеальный компилятор, это невозможно, требуется сделать максимально хороший с ограничением по времени разработки. Если фичу сложно сделать, и она имеет малую ценность — нафиг её, даже если есть валидные сценарии и план резолва неопределенности.
                                                                                                                                                              –1
                                                                                                                                                              Не вижу повода не верить человеку, который эту экспертизу провел.
                                                                                                                                                              Ну хотябы потому что нет ни одного конкретного примера.
                                                                                                                                                              Если фичу сложно сделать, и она имеет малую ценность — нафиг её,
                                                                                                                                                              Т.е. религиозные соображения
                                                                                                                                                                0
                                                                                                                                                                Скорее экономические соображения. Вот «малая ценность» можеь быть объявлена из «религиозных».
                                                                                                                                                0
                                                                                                                                                Поведение это трейты. Похоже не интерфейсы, но немного другое все-таки. У них и названия другие. Интерфейсы — это IEnumrator, IList, ICollection… Трейты — Display/Debug/Clone/Copy/…

                                                                                                                                                Так трейты — это и есть множественное наследование. Если трейты ок — то и множественное наследование же ок?

                                                                                                                                                  0
                                                                                                                                                  Трейты — не наследование, они не реализуют отношение «является». По сути трейты чисто технический механизм переиспользования кода. Один и тот же трейт, например, может реализовывать разные интерфейсы, не связанные друг с другом наследованием.
                                                                                                                                                    0
                                                                                                                                                    Трейты — не наследование, они не реализуют отношение «является».

                                                                                                                                                    Реализуют, конечно, с чего бы нет?


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

                                                                                                                                                    Ну, как и наследование :)


                                                                                                                                                    Один и тот же трейт, например, может реализовывать разные интерфейсы, не связанные друг с другом наследованием.

                                                                                                                                                    В точности так же как и один и тот же класс может реализовывать два разных интерфейса, не связанных друг с другом наследованием.


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

                                                                                                                                                      0
                                                                                                                                                      Реализуют, конечно, с чего бы нет?

                                                                                                                                                      Зависит от реализации, конечно. В моём основном языке трейты не реализуют "являются", результат операции тип $obj instanceof TrateName всегда false.


                                                                                                                                                      Ну, как и наследование :)

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


                                                                                                                                                      В точности так же как и один и тот же класс может реализовывать два разных интерфейса, не связанных друг с другом наследованием.

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

                                                                                                                                                        0
                                                                                                                                                        В моём основном языке трейты не реализуют "являются", результат операции тип $obj instanceof TrateName всегда false.

                                                                                                                                                        Ну это неконсистентное поведение instaceof в вашем языке, не более того. Если класс реализует трейт, то он является соответствующим подтипом и то, что у вас instaceof не соответствует отношению подтипирования в языке — проблема, конечно.


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

                                                                                                                                                        А иерархии абстракций для чего создаются? ;)


                                                                                                                                                        В классе указывается, что он реализует интерфейсы, в трейтах нет. Выржение"реализует интерфейс" в отношении трейтов следует понимать в смысле утиной типизации, а не строгой.

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


                                                                                                                                                        То есть вы говорите сейчас не о трейтах, а о некоторой фиче, которая называется трейтами и на них похожа, но ими по факту не является.
                                                                                                                                                        Действительно, такая фича может и отличаться от наследования, но если говорить о трейтах не в контексте конкретной реализации в конкретном языке, то от наследования они не отличаются.

                                                                                                                                                          0
                                                                                                                                                          Класс не реализует трейт, он собирает себя из трейтов и собственных объявлений.

                                                                                                                                                          Ну или приведите своё каноничное определение трейта.
                                                                                                                                                            –1
                                                                                                                                                            Класс не реализует трейт, он собирает себя из трейтов и собственных объявлений.

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


                                                                                                                                                            Ну или приведите своё каноничное определение трейта.

                                                                                                                                                            Трейт — это ровно тот же самый абстрактный класс, просто для его наследования зафиксирован более простой и ясный алгоритм выбора конкретного метода, когда у вас при наследовании получается конфликт имен. С-но реализация данного алгоритма выбора при наследовании — и есть "трейты".
                                                                                                                                                            Ниже было верно замечено, что обычно трейты не должны иметь состояний, но это несущественно, т.к. легко обходится, пусть и за счет несколько искусственных конструкций (трейт может расширять класс с состоянием).

                                                                                                                                                              0
                                                                                                                                                              трейты не должны иметь состояний, но это несущественно
                                                                                                                                                              Это существенно, т.к. самый главный аргумент против множественного наследования, которого нет в трейтах. Наследуясь от разных классов, нет возможности не забирать поля одного класса, если они уже есть в другом. С трейтами поля не дублируются никак.
                                                                                                                                                              т.к. легко обходится, пусть и за счет несколько искусственных конструкций (трейт может расширять класс с состоянием)
                                                                                                                                                              Вы хотите искусственно придумать себе граблей? Как сделать плохо, если нет множ. наследования, но есть трейты? Совсем запретить говнокод язык не может.
                                                                                                                                                                0
                                                                                                                                                                Можно узнать источник этого определения? Естественно каноничного, а не из спеки вашего любимого языка, потому что в моём любимом оно, мягко говоря, другое.
                                                                                                                                                                  –2
                                                                                                                                                                  Наследуясь от разных классов, нет возможности не забирать поля одного класса, если они уже есть в другом.

                                                                                                                                                                  Та же самая проблема возникает при наследовании методов.
                                                                                                                                                                  Кроме того — любое поле можно заменить набором методов.


                                                                                                                                                                  Вы хотите искусственно придумать себе граблей? Как сделать плохо, если нет множ. наследования, но есть трейты?

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

                                                                                                                                                                    0
                                                                                                                                                                    Та же самая проблема возникает при наследовании методов.
                                                                                                                                                                    Не возникает.
                                                                                                                                                                    Кроме того — любое поле можно заменить набором методов.
                                                                                                                                                                    Поле увеличивает sizeof объекта, увеличивая кол-во его возможных состояний, а метод — не увеличивает sizeof. Может, вы в это высказывание вкладываете какой-то особенный смысл, но я это прочитал как то, что вы нашли способ сжимать информацию без потерь до 0 байт.
                                                                                                                                                                    Если трейты точно так же позволяют наступать на грабли, то чем они отличаются от обычного множественного наследования?
                                                                                                                                                                    Так всё развитие языков программирования — это выдумывание всякого синтаксического сахара, чтобы быстрее писать код и меньше наступать на грабли. Трейты отличаются от обычного множественного наследования тем, что их массовое использование не приводит к типичных граблям, которые появляются при массовом использовании множественного наследования.
                                                                                                                                                                      –1
                                                                                                                                                                      > Не возникает.

                                                                                                                                                                      С чего бы вдруг? проблемы то все те же.

                                                                                                                                                                      > Поле увеличивает sizeof объекта

                                                                                                                                                                      При чем тут вообще sizeof?

                                                                                                                                                                      > а метод — не увеличивает sizeof

                                                                                                                                                                      Зависит от реализации. Может и увеличивать спокойно.

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

                                                                                                                                                                      Трейты — и есть множественное наследование, так что ваши слова бессмысленны.
                                                                                                                                                                      Вы хотите сказать, что определенные правила разрешения конфликтов при множественном наследовании приводят к тому, что получается избежать некоторых типичных граблей? Это да.