1. Куча / Говнокод #20248

    +5

    1. 1
    2. 2
    3. 3
    Тут недавно оказия вышла. В одном чатике, где были несколько программистов и математик, задали вопрос:
    
    В каком порядке наследование верное целые числа -> рациональные или наоборот?

    Запостил: laMer007, 22 Июня 2016

    Комментарии (92) RSS

    • Баян конечно
      Ответить
      • а какая разница? оба подмножества множества комплексных чисел.
        Ответить
    • Целое число можно представить рациональным, но не наоборот. Смекаешь?
      Ответить
      • Не, давай ты прямо ответишь, что от чего наследовать. Не уклоняйся от ответа) Удивительно, но я нашел не менее 4тырех разных точек зрения по этому вопросу в среде программистов, притом что они знают то, о чём ты говоришь.
        Ответить
        • Огласите весь список точек зрения, пожалуйста.
          Ответить
          • Не знаю про что он, но в нашей конфе звучало много чего:

            1) целые->рациональные
            2) рациональные->целые
            3)
            целые->числа
            рациональные->числа
            4)
            целые
            рациональные

            И ещё всякие модификации типа по интерфейсу на каждую операцию или интерфейс на все операции и и отдельный интерфейс на деление для рациональных
            Ответить
            • Ну тогда есть еще вариант: целые <-> рациональные (кто сказал, что нельзя наследоваться в обе стороны?).
              Ну и еще зависит от реализации ОО: можно ли удалять методы, заставляет ли язык сохранять те же типы / сужать / расширять типы методов.
              Ответить
              • целые <-> рациональные
                Что-за чушь?
                Ещё скажи:
                5)
                числа->целые
                числа->рациональные
                ))
                Ответить
                • > Ещё скажи:
                  > числа->целые
                  Как будто что-то плохое.
                  При крестонаследовании потомок - это уточнённый вореант родителя.
                  struct Int {
                    int mantissa;
                  };
                  struct Double: public Int {
                    int exponent;
                    int sign;
                  };

                  Если к инту добавить ещё немного информации, будет плавающий питух (математически: если к инту добавить бесконечность знаков, будет риал).
                  У произвольного числа можно взять целую часть. А вот целое - недостаточно специально (наследование - специализация) для того, чтобы быть произвольным числом.
                  Ответить
                  • однако, чтобы в этой схеме наследования срослось:
                    Int a = 1;
                    Double b = Double(1, 3);  // 1e3
                    Int c = b; // 1
                    Double d = a;  // 2
                    тебе надо попыхтеть и доделать:
                    - оператор приведения Double к прямому предку (к Int), ибо стандартный в //1 тебе вернет 1, а не 1000
                    - оператор присваивания любого объекта в иерархии в Double (и тут, возможно, без шаблонной магии не обойтись)
                    Ответить
    • Наследование не нужно.
      ℕ ∈ ℤ ∈ ℚ ∈ ℝ ∈ ℂ
      Ответить
      • Наверное ты имел в виду ⊂.
        Именно это отношение наследование и выражает. Подкласс - это подмножество объектов базового класса.
        Ответить
        • Наследование (классическое крестобляское-жабное) - очень плохо подходит для выражения отношений между множествами в математике.

          Проблемы немедленно начинаются, когда вводим класс не ложащийся в цепочку, например 𝔸 ∈ ℂ, но 𝔸 ∉ ℝ.
          Или 𝕀ℕ, которое как ℕ только мнимое.
          Ответить
          • > Или 𝕀ℕ, которое как â„• только мнимое.

            Если я правильно понял, то 𝕀ℕ — это натуральные числа, домноженные на мнимую единицу? Тогда свойство «как ℕ только мнимое» не работает, ибо в 𝕀ℕ не работает умножение: произведение двух мнимых чисел будет вещественным числом.
            Ответить
            • >ибо в 𝕀ℕ не работает умножение
              Почему не работает. Метод должен вернуть целое.
              В терминах ООП придётся нагородить кучу методов с явными типами. Больше типов => больше бойлерплейтных методов.

              class INatural{
                INatural   add(INatural a){...}
                Zeloe      mul(INatural a){...}
                INatural   mul(Natural a){...}
                IZeloe     sub(Natural a){...}
                IZeloe     sub(INatural a){...}
                IRatio     mul(Ratio a){...}
                IRatio     div(Ratio a){...}
                IRatio     div(IRatio a){...}
              ...
              }
              Ответить
            • > свойство «как â„• только мнимое» не работает

              Видимо потому, что это не свойство. Вроде не было утверждения, что ещё и операции на элементами 𝕀ℕ ведут себя так же, как в ℕ.

              > в 𝕀ℕ не работает умножение

              В ℕ иногда не работает вычитание и деление, но это не повод считать ℕ нинужным.
              Ответить
      • â„• ⊂ ℤ ⊂ â„š ⊂ ℝ ⊂ â„‚ ⊂ ℍ ⊂ 𝕆 ⊂ 𝕊.
        Хотя о чём это я? Седенионы не нужны, да и октавы тоже. Можно остановиться на кватернионах.

        Главное всё-таки, что тут нужно писа́ть знак ⊂ (включение), а не ∈ (принадлежность), потому что ℤ — это множество чисел, а не множество множеств.
        Ответить
        • Да Вы же человек-энциклопедия. Программирование, веб- и сео-питушня, типографика и дизайн, лингвистика, история, математика (и это только то, чо пришло на мой скромный ум за пару минут) - ничто не ускользнуло от Вашего зоркого ока разума.
          Ответить
          • Тут недавно оказия вышла. В одном чатике, где были несколько программистов и математик, задали вопрос:
            
            В каком порядке наследование верное: натализации -> кобенации -> вореции -> генереции -> имперации или наоборот?
            Ответить
            • Кстати, ничего не могу найти на эту тему. Вот что у меня получается:
              https://clck.ru/9xmhy
              Ответить
            • Вооо. В правильной постановке ворцпоса - кроета 39721% зожание отвеа.
              Ответить
    • ИМХО

      abstract class Number
      public class RationalNumber extends Number
      public class NaturalNumber extends Number
      Ответить
    • Я уже не раз писал, как в университете порезал мозг об ООП (читай — наследование), когда пытался смоделировать математику. ООП нинужно, им можно выразить примерно полпроцента отношений между сущностями.
      Всё, что есть хорошего в ООП, на самом деле придумано ещё Дэвидом Парнасом.
      Ответить
      • А что использовать вместо ООП?
        Ответить
        • Ассемблер. С его помощью что угодно выражается.
          Ответить
          • не все.

            Нужно писать на машинных кодах. Транслятор просто может не знать новые опкоды Вашего цпу
            Ответить
            • А где гарантия, что программист знает все опкоды своего ЦПУ?
              Ответить
              • писать нужно на VB
                где гарантия что программист знает еще какой-нибудь язык?
                Ответить
              • А где гарантия, что процессор знает все опкоды вашей проги?
                Ответить
            • Подытоживая, если можно писать -- не пиши.
              Ответить
      • отучаемся говорить за всех.

        Для математики или для лоу левела очевидно ООП плох. А для выражения, например, GUI отличен.
        И для бизнес логики не плох.
        Ответить
      • > примерно полпроцента отношений между сущностями

        О, я вспомнил годное применение ООП!

        В STL тэги итераторов моделируются через наследование, чтобы выбирать в компайл-тайме оптимальную реализацию алгоритмов. google://tag+dispatching

        И то надо было через компайл-тайм capability query сделать — не осилили.
        Ответить
        • Ха-ха. Даже этого не осилили сделать нормально. Выразить, например Random-access output iterator например сложно. Да и вообще то, что forward_iterator это непременно inpit_iterator это плохо. Нормально выразить ostream_iterator, который не-forward и позволяет только писать в него, или raw_storage_iterator, который random_access, но тоже позволяет только писать, трудно. Особенно факт, что читать из них не нужно.

          Опять же, contiguous_iterator_tag не запихали в стандарт, потому что что-то у кого-то ломается. В общем там плохо.
          Ответить
          • > Даже этого не осилили сделать нормально

            Ну я и говорю, там по уму через проверку возможностей в компайл-тайме надо делать, и не заставлять программистов писать нинужные инкременты / экскременты там, где они не имеют смысла. Не является итератор регулярным? Просто не нужно реализовывать копирование (правда, без move-семантики тогда было бы трудновато). Если есть перегруженные скобки — значит, random access, если есть инкремент — значит, можно двигать вперёд, etc.
            Ответить
          • > Даже этого не осилили сделать нормально
            > forward_iterator это непременно inpit_iterator
            В буст::итераторс нормально запилили. Там больше классов, все отделено и все это конвертится на всякий случай для убогого легаси интерфейса итераторов стл, если ими пользуется легаси код. Могли бы и в стандарт с++ внести вместе с этим конвертером
            Ответить
    • Ох блин. Тараканы и комары наследуются от насекомых, насекомые наследуются от еще какой-то там хрени, ну например они гетеротрофы, а еще все насекомые обладают например какой-то там примитивной нервной системой, так что они наследуют свойство живых организмов с нервной системой, ну а еще все насекомые способны перемещаться в пространстве, так что они должны наследовать "двигающийся" ну и так далее.

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

      Короче, когда-то давно я начал выдумывать свой ПРИНЦИПИАЛЬНО НОВЫЙ ЯП чторы через графы, а не каким-то там ебнутым наследованием http://dump.bitcheese.net/files/ytykavi/test.svg вот это например, не обращайте внимание на опечатки и прочую хрень, я тут пытался как бы обобщения для сортировок сделать. Там еще много чего недописано, про всякие там проекции футамуры, специализации, суперкомпиляции, преобразованиями над графом программы, получение из графа зависимостей ярусно-параллельной формы, приделать ко всему этому какую-то систему символьных вычислений, короче хуйпоймичто
      Ответить
      • Знаешь, вот есть такой Царь. Так он царь лоу-левела. А ты царь хай-левела
        Ответить
        • Царь хайлевела — это CHayT.
          Ответить
          • А есть еще царь пиздабольства в одной жаркой стране
            Ответить
            • > Средние температуры июля от +14 в горах до +22 °C в долинах.
              > Жаркая погода бывает редко, однако 13 августа 2003 года температура составила +37,0 °C, став самой высокой за всю историю метеонаблюдений.

              В жаркой разве? По-моему, типичная температура для умеренного климата.
              Ответить
              • нее) этот царь разве что шамилю царем приходится
                Ответить
                • А, вспомнил царя из действительно жаркой страны. Мастер производить впечатление. Но он вроде и по делу пишет или так только кажется?
                  Ответить
                  • Он пишет на темы на которые все равно никто не поймет что он написал.
                    Ответить
                  • В основном он дедает вид
                    Ответить
                • У вас памятник шамилю еще не открыли?
                  Ответить
                  • Какой-то говносайт пишет, что поставили: http://www.russkiymir.ru/publications/142937/

                    Ещё пишут, что на Украине поставили: http://pikabu.ru/story/_2002626

                    И в США тоже поставили: http://dagstadion.narod.ru/art183.html

                    И в Турции поставили...

                    А почему ты так о Шамиле беспокоишься?
                    Ответить
                    • Ну мост кадырки открыли.
                      Ответить
                      • Ага. И после всего этого почему-то русские — фашисты, националисты, имперцы и т. п.
                        Ответить
                        • Русня - долбоебы.

                          >имперцы
                          АТО!

                          >фашисты
                          У фашистов главное - государство, так что да.
                          Ответить
                          • > У фашистов главное - государство, так что да.
                            Нестыковка.
                            Ответить
                  • Привет! Как дела у Шамиля?
                    Ответить
            • Причем тут рашка?
              Ответить
          • стоит один пост в зелёненький не покрасить, как сразу в цари записали?
            Ответить
    • Ну если уж нужно строго натянуть сову на глобус, то т. к. наследование должно являться отношением is-a, то целые должны быть потомками рациональных, иначе получаем нарушение принципа Лисков.
      Ответить
      • И походу придётся делать отдельно интерфейс Integer и реализацию IntegerImpl, иначе мусор от реализации комплексных и вещественных чисел будет болтаться в интах...
        Ответить
        • Я за общего предка и двух наследников: Целые и Рациональные.

          Целые через имплисит конструкторы Рациональных должен конвертиться в Рациональные. Рациональные через эксплисит оператор каста Рациональных должен конвертиться в целые. В таких условиях все дозволенности крестов с их кастами о наследовании можно не заботиться, хоть убирай вообще
          Ответить
        • >придётся делать отдельно интерфейс Integer и реализацию ntegerImpl
          >иначе мусор от реализации комплексных и вещественных чисел будет болтаться в интах...

          Но как же? Наследование это ведь ОЧЕНЬ удобный и эффективный способ представления отношений между множествами и сучностями.

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

            И вот на кодревью они чуть ли не драки у нас из-за этого устраивают.
            Ответить
            • А есть апологеты: "наследование - не нужно ни в каком виде".

              >на кодревью они чуть ли не драки у нас из-за этого устраивают.
              А вы, ребята, как ни наследитесь, в программисты всё-равно не годитесь.
              Ответить
              • Зато в быдланы как я погляжу отлично годятся
                Ответить
      • > целые должны быть потомками рациональных

        Целочисленные синусы, косинусы и т. п. существуют?
        Ответить
        • Ты это к чему?
          Ответить
          • В случае наследования целых от рациональных, а рациональных от вещественных целые должны унаследовать тригонометрические функции, корни, логарифмы и прочие функции с плохо предсказуемым результатом.
            Ответить
            • Ну они и "унаследуют" тригонометрические функции возвращающие вещественные значения.
              Смысл в том, что в функцию Float sin(Float x) можно передать Integer, унаследованный от Float. Наследование не подразумевает, что внезапно появится функция Integer sin(Integer x).
              Ответить
              • Плюсанул, но типа взорвата не может сужаться.

                >Наследование не подразумевает, что внезапно появится функция Integer sin(Integer x).

                Как раз наоборот. Контрвореантность и ковореантность.
                Наследование допускает сужение return-типа. Но не расширение, то есть мы можем сделать так, зная что не выйдем за пределы целых:
                Integer add(Integer b)

                При этом в паренте будет: Ratio add(Ratio b)

                Но не допускает сужение аргумента. Т.к. если Integer extends Ratio то он тоже должен поддерживать
                Ratio add(Ratio b)
                но может быть реализован как
                Integer add(Ratio b)
                ибо Integer - подмножество Ratio.
                Ответить
                • Это про вореции?
                  Ответить
                • Кстати, можно же поддержать и так:
                  Ratio add(Ratio b); // для совместимости с родителем
                  Integer add(Integer b); // для удобства и оптимизации
                  Ответить
                  • О чём и речь.
                    >Ratio add(Ratio b); // для совместимости с родителем

                    Причём такой метод вовсе не обязательно делать. Он уже есть в родителе родителя. Достаточно реализовать какой-нить общий toComplex/toRatio и сразу появляются add/sub/mul/div, etc
                    Ответить
                • Корочи, не знаю, как в джави, а в плюсах у меня были бы не методы, а Float operator+(Float, Float) и Integer operator+(Integer, Integer). При сложении двух интежеров конпелятор выберет вторую перегрузку. Для всех остальных кобенаций аргументов - первую.

                  Upd: борманд выше показал, что в джави можно так же.
                  Ответить
                  • но.. куда ты денешь полиморфизм...
                    Ответить
                    • Дык всё ок будет, если Integer порождён от Float и может полноценно им прикинуться, не нарушая принципа Лисков.
                      Ответить
                      • я примерно об этом
                        http://coliru.stacked-crooked.com/a/188ea7ad76c9a108
                        (мультиметоды в кресты ведь так и не завезли?)
                        Ответить
                        • Хочешь статического полиморфизма - работай явно с джвумя Integer'ами. Не можешь доказать статически, что у тебя там Integer - получишь более общую перегрузку с Number/Float (не забываем, что согласно принципу Лисков Integer всегда можно передать в качестве Number или Float).

                          http://coliru.stacked-crooked.com/a/7f7d11994da28f91
                          Ответить
                          • я не хочу ничего доказывать
                            я просто хочу хорошее сложение
                            Ответить
                            • Ну ты же не жалуешься, что сложение (float)4 + (float)5 даёт в ответе (float)9? Вот и тут будет так же.

                              Сложил 2 инта - получил инт. Сложил флоат (который мог быть как целым так и дробным) и инт - получил флоат и т.п.
                              Ответить
                            • А что не так со сложением? Операция сложения флоатов определена. Динамический полиморфизм там не нужен.
                              Ответить
                              • > Динамический полиморфизм там не нужен.
                                В общем-то да. Тогда можно даже не делать их интерфейсами и не порождать их друг от друга, а просто дать Integer'у операторы каста в Ratio и Float, Ratio оператор каста во Float и т.п.

                                И если мы складываем 2 разных типа, один из них просто апкастнется во второй (что в общем-то и происходит с обычными int и float)...
                                Ответить
                                • Правильно. А то еще запишут в интежер число пи по мутабельной ссылке.
                                  Ответить
                                  • Wait. Как это вообще работает? Мутировать объект дочернего класса так, как будто это базовый класс - это ведь фигня какая-то в общем случае.
                                    Ответить
                                    • > Мутировать объект дочернего класса так, как будто это базовый класс
                                      Это и не работает :)
                                      Ответить
                                    • > Мутировать объект дочернего класса так, как будто это базовый класс - это ведь фигня какая-то в общем случае.

                                      Эта проблема стара и убога как само ООП
                                      https://en.wikipedia.org/wiki/Circle-ellipse_problem
                                      Ответить
                                      • > Эта проблема стара и убога как само ООП
                                        Ааа, надо внести это в золотой фонд цитат
                                        Ответить
                                      • Мутаторы нинужны. Нет мутаторов - нет проблемы :3
                                        Ответить
                                      • Казалось бы - причём тут наследование?

                                        Some authors have suggested reversing the relationship between circle and ellipse, on the grounds that an ellipse is a circle with more abilities. Unfortunately, ellipses fail to satisfy many of the invariants of circles; if Circle has a method radius, Ellipse must now provide it, too.

                                        Как его ни крути, всюду говно.
                                        Ответить
                                  • >в интежер число пи по мутабельной ссылке.

                                    >>Число.
                                    >>Мутабельное.

                                    >>>Атомарная херь
                                    >>>Мутабельная.
                                    До такого дна наверное даже не все оопшные крестухи додумаются. И там где число, там же обычно и хеш-код рядом.
                                    Ответить
                                    • Записывать что-то в параметры, переданные по неконстантной ссылке - это обычная практика, особенно у божественных сишников. И вот есть у тебя функция void add(Float &x, const Float &y), и ничего не мешает передать первым параметром Integer.
                                      Ответить
                                      • >это обычная практика, особенно у божественных сишников

                                        Так о чём и речь. Уже даже крестобляди не оптимизируют на мутабельных спичках шишках. std::move, все дела.

                                        Остались только Цари.
                                        Ответить
              • > Float sin(Float x) можно передать Integer
                Наверное ты хотел сказать)))) :
                Float sin(Float* x) можно передать Integer* ну или хотябы const ...&
                Ответить
                • Че хотел сказать, то и сказал)))) Integer во Float сконвертируется благодаря конструктору копирования Float(const Float &).
                  Ну и это плюсодетали, а там речь про наследование вообще.
                  Ответить

    Добавить комментарий