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

    Во-первых, не переделывать, a overload-ить для удобства использования. Во-вторых, мотив прозвучал "во первЫх строках" сей темы - народ с подачи самого Борланда привык к классам и методам и соотв-но требует "хлеба и зрелищ" :D Мне лично по барабану и я в больш-ве случаев прекрасно обхожусь функциями, как впрочем и не пользуюсь некоторыми "бестолковыми", но горячо любимыми в народе, классами типа TFileStream :)
    Сообщение отредактировано: leo -
      Вообщем, моя точка такова, сделано не совсем у Borland'а не совсем правильно, нужно было реализовать два варианта когда compare должна быть методом и когда должна быть общей (глобальной) и не было бы проблем.
        Цитата Romkin @
        В данном случае метод просто унаследован от TList, а там чаше всего требование именно метода ограничивает, мало ли на что я там ссылки хранить буду

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

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

        Вобщем, ИМХО, это пережиток. Надо все-таки в сторону методов смотреть.
          Цитата Felan @
          Как тут уже сказали, этот метод не обязательно должен принадлежать контейнеру. Он может принадлежать элементу. А элементы могут быть разными, но реализовывать один интерфейс для сравнения, если по смыслу задачи это надо.

          Цитата Romkin @
          Можно было ее сделать методом класса, но не сделали потому, что контейнер TObjectList может хранить и "чужие" объекты, у которых метода сравнения нет и сделать нельзя (о хелперах не говорю).


          Зачем писать лишнее? Все сделано грамотно.
            Цитата Felan @
            Раз идеология с процедурной сменилась на объектную, нефиг за собой артефакты таскать. И с точки зрения цельности абстракции никому не принадлежащая функция как-то странно выглядит...

            Полностью с тобой согласен
              Ладно, все равно уже наоффтопили...

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


              А я в этом не уверен. Возьмем Java или C#. На 100% объектный? Многим покажется что да. Но как тогда объяснить такое загадочное явление, как статические методы, которые ни к объектам ни к классам никакого отношения вообще не имеют, если разобраться? А ведь они введены как раз из-за того, что в 100% объектном языке нет и не может быть бесхозных процедур/функций. Просто произошла подмена понятий и класс взял на себя функцию пространства имен, которую в Delphi традиционно выполняет юнит.

              Добавлено
              Кстати, а как быть, когда мне нужна сортировка по разным критериям одновременно? У какого класса делать методы сравнения? У контейнера или элементов? Если первое, то в классе контейнере в общем случае невозможно учесть все типы элементов, которые могут в нем содержаться. Если второе, то в классе элементов невозможно учесть все критерии, по которым я захочу их сравнивать. Если делать гибко, то ничего лучше внешней функции не придумаешь. Ну, разве что классы-сортировщики с единственным статическим методом Compare, но эта "красота" за уши притянута, а почему - я писал выше.
                Ins, хорошее замечание :)

                Действительно, если объявить компаратор как метод, и если у меня нет класса (например, я использую класс списка в простой процедуре и мне надо его отсортировать), то я вынужден писать такое:

                ExpandedWrap disabled
                  type
                    TDummy = class
                      class function Compare(Item1, Item2: Pointer): Integer;
                    end;
                   
                  class function TDummy.Compare(Item1, Item2: Pointer): Integer;
                  begin
                    // ...
                  end;


                Вместо:

                ExpandedWrap disabled
                  function Compare( { List: TSomeList; } Item1, Item2: Pointer): Integer;
                  begin
                    // ...
                  end;


                Оба варианта (метод/функция) являются удобными в каких-то отдельных случаях. И нет универсально удобного способа.

                Если отбросить в сторону стилевые предпочения (и охота вам проблемы на пустом месте создавать), то самый важный момент связан с тем, можете ли вы пердать внешние данные в компаратор или нет. Т.е. с передачей user-data.
                Если компаратор является методом, то все дополнительные данные могут передаваться через объект - в конце концов метод это же код + данные.
                Если компаратор является функцией, то нет уже умалчиваемого способа задания внешних данных. Обычно такую передачу делают через обобщённый user-param типа Pointer или Cardinal. Через него можно передать любые данные, какие вам надо. Например, как это сделано в TStringList:

                ExpandedWrap disabled
                    TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer;


                Окей, компаратор TObjectList не имеет user-param-а. Почему? Хороший вопрос :) Может просчёт, а может сделали специально, ибо просто таково назначение TObjectList-а - служить базой для других списочных классов. В частности, таких классов, у которых элементы списка связаны с самим списком. Т.е. каждый элемент имеет указатель на свой список - вот вам и место передачи user-param-а. Конечно, есть ещё TCollection с TCollectionItem - но это уже довольно далеко от TObjectList. А в промежутке между ними как раз и находятся пользовательские классы типа:

                ExpandedWrap disabled
                  type
                    TMyItemList = class;
                   
                    TMyItem = class(...)
                    private
                      FList: TMyItemList;  
                    end;
                   
                    TMyItemList = class(TObjectList)
                      ...
                    end;
                   
                  function SortMyListByName(Item1, Item2: Pointer): Integer;
                  var
                    List: TMyItemList;
                  begin
                    List := TMyItem(Item1).FList;
                    // ...
                  end;
                  Цитата --Ins-- @
                  А я в этом не уверен. Возьмем Java или C#. На 100% объектный? Многим покажется что да. Но как тогда объяснить такое загадочное явление, как статические методы, которые ни к объектам ни к классам никакого отношения вообще не имеют, если разобраться?

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

                  Класс это абстракция. Основное понятие ООП. Плюс этому то, что говорил CodeMonkey про параметризацию компоратора.
                  А в отдельный класс эти методы выносить или для каждого свой, или еще как-то это вопрос дизайна, который каждый для себя решает сам. Нет понятия правильного/неправильного дизайна. Есть лучший/худший, и многие "законодатели мод" считают что объектный дизайн лучше, чем процедурный. :)
                    Цитата Felan @
                    а статические методы к классу.


                    А ты не путаешь class methods Delphi со static-методами Джавы и Шарпа? Эт не одно и то же ;)
                      Нет. Не путаю.

                      Это просто абстракция, но это средства упорядочивания логической структуры.

                      Покажи мне пример, как вызвать статический метод джавы или шарпа без имени класса. Без извращений с отражениями.
                      Если сможешь, посыплюсь пеплом и признаю твою правоту, иначе ты не прав.
                        Felan, ты не понял. Смотри, классовый метод в Delphi действительно работает с классом. А статик-метод в Java - нет. Класс для него является лишь простанством имен, подобно тому, как для обычной процедуры пространством имен в Delphi является юнит. Так в чем же принципиальная разница между статик-методом и функцией/процедурой? В том, что для вызова статик-метода пространство имен указывать обязательно, а для обычной процедуры - нет? ;) Так это чаще всего преимущество. Не нужно ради одной подпрограммы городить целый класс и каждый раз его указывать.

                        Добавлено
                        Вообще, почему в TList параметр функция, а не метод - понятно. TList - это контейнер произвольных данных, не обязательно объектов, так зачем же вешать объектную оболочку над необъектной сущностью. Да и исторически так сложилось. Почему не сделали overload-метод у TObjectList, скажем? Да фиг его знает, не посчитали необходимым. Но разве тяжело ввести его самому? Если пишешь наследника - просто объявляешь свой метод, если используешь сам TObjectList - хелпер в руки. ;)
                          Цитата --Ins-- @
                          Так это чаще всего преимущество. Не нужно ради одной подпрограммы городить целый класс и каждый раз его указывать.

                          + 1.
                          Тот же Delphi например. Зачем надо было RaiseOuterException делать простым статическим методом класса?

                          Теперь вместо компактного (возможного) варианта:

                          ExpandedWrap disabled
                            try
                              ...
                            except
                              on E: Exception do
                              begin
                                ...
                                raiseOuter(Exception.Create(...));
                              end;
                            end;


                          Нужно писать:

                          ExpandedWrap disabled
                            try
                              ...
                            except
                              on E: Exception do
                              begin
                                ...
                                Exception.RaiseOuterException(Exception.Create(...));
                              end;
                            end;


                          А чего стоит

                          ExpandedWrap disabled
                            TCharacter = class sealed
                          ,

                          состоящий только из статических классовых методов! Причём, чтобы не корячится каждый раз с TCharacter.ToLower, в этом же модуле введены процедуры-переходники. Которые ровным счётом ничего не делают, кроме как вызывают методы TCharacter. Ужас. Не иначе как для совместимости с ???... не знаю, .NET, может быть. Скоро Integer станет sealed-классом со статическими операторами плюс и минус :)))

                          Цитата --Ins-- @
                          хелпер в руки

                          Да-да-да, отличная вещь! :) Жаль только больше одного нельзя.
                            Цитата --Ins-- @
                            Felan, ты не понял. Смотри, классовый метод в Delphi действительно работает с классом. А статик-метод в Java - нет. Класс для него является лишь простанством имен, подобно тому, как для обычной процедуры пространством имен в Delphi является юнит. Так в чем же принципиальная разница между статик-методом и функцией/процедурой? В том, что для вызова статик-метода пространство имен указывать обязательно, а для обычной процедуры - нет? ;) Так это чаще всего преимущество. Не нужно ради одной подпрограммы городить целый класс и каждый раз его указывать.

                            Это ты не понял. :)
                            Да, "...класс для него лишь пространство имен..." и это позволяет более правильно и строго следить за структурой проекта, областями видимости и т.п. Принципиальной разницы нет. Так же как ее нет в итоге между программой написанной на разных языках (не будем разводить флейм про скорость и подобное). Еще раз говорю, это всего лишь средство организации абстракций из которых состоит проект. И сделано это для того, что бы не использовать одновременно две парадигмы, процедурную и объектную.

                            С точки зрения процедурной парадигмы - ты прав.
                            С точки зрения объектно-ориентированной - я прав.

                            Остается выяснить какая парадигма правильная :) :) :)

                            Но мы же не будем этим бредом заниматься?

                            Лично мне нравится объектная. Она мне удобнее.

                            :)

                            ЗЫЖ Предлагаю мировую. А то это никогда не кончится :)
                              Цитата Felan @
                              Принципиальной разницы нет

                              в Java есть виртуальные классовые методы??
                              1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
                              0 пользователей:
                              Страницы: (3) 1 2 [3]  все


                              Рейтинг@Mail.ru
                              [ Script execution time: 0,0882 ]   [ 14 queries used ]   [ Generated: 18.07.25, 00:53 GMT ]