На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
  
> [Delphi] Методы vs функции, классовые vs статик методы и всё остальное.
    Есть наследник от TObjectList:
    ExpandedWrap disabled
      type
        TMyList = class(TObjectList)
        private
          FSign: integer;
          function Compare(Item1, Item2: Pointer): Integer;
        public
           procedure Sort(aSign); overload;
        end;  
      ...
      function TMyList.Compare(Item1, Item2: Pointer): Integer;
      begin
       
        if FSign > 0 then
          Result :=...
        else
          ...
      end
       
      procedure TMyList.Sort(aSign); overload;
      begin
       
        FSign := aSign;
        inherited Sort(Compare); //здесь на этапе компиляции возникает ошибка
      end;

    Проблема в том, что при передаче в Sort ф-ции Compare возникает ошибка как быть? Неужели я должен делать Compare глобальной?
    Сообщение отредактировано: jack128 -
      функция <> метод
        Цитата Domino @
        функция <> метод

        Ну так как передать, не ужели глобальную ф-цию заводить?
          Так у тебя Sort че принимает то? И че ты туда передаешь?

          Она у тебя принимает функцию, а не метод. Ты же наследника делаешь, ну сделай, что бы он у тебя метод принимал, а предку функцию сделай, которая этот метод вызывать будет.
          Сообщение отредактировано: Felan -
            Цитата Felan @
            Type
            TCompareFunction = function(Item1, Item2: Pointer) of object;


            Передавать нужно простую функцию, а не метод.

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


            Добавлено
            Цитата DelphiLexx @
            Неужели я должен делать Compare глобальной?


            Что значит глобальной?
              Цитата Felan @
              Она у тебя принимает функцию, а не метод. Ты же наследника делаешь, ну сделай, что бы он у тебя метод принимал, а предку функцию сделай, которая этот метод вызывать будет.

              Что-то не совсем понял, можно на примере

              Добавлено
              Цитата Демо @
              Передавать нужно простую функцию, а не метод.

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

              Добавлено
              Цитата Демо @
              Что значит глобальной?

              Как что, глобальная ф-ция - это ф-ция объявленная в секции interface и реализованная в секции implementation'a и не являющаяся методом какого-либо класса.
                Объяви ее только в implementation.
                  Цитата Romkin @
                  Объяви ее только в implementation.

                  Не хотел бы я использовать в Sort, то что не принадлежит классу, не граммотно это.
                    Цитата DelphiLexx @
                    Не хотел бы я использовать в Sort, то что не принадлежит классу, не граммотно это.

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


                        Ну значит сортировку вручную реализовывать.

                        Либо второй вариант - принять, что не класс является единицей реализации, а и модуль, в котором он описан.
                          Цитата Domino @
                          Абсолютно согласен с этим утверждением.

                          И зря. Какое отношение имеет оператор сравнения к контейнеру?!
                            Цитата Domino @
                            Цитата (DelphiLexx @ Сегодня, 14:55)
                            не граммотно это
                            Абсолютно согласен с этим утверждением.

                            Тоже согласен, но что поделать, если в данном случае в базовом классе именно функция?

                            Не уверен, но может быть так попробовать:
                            ExpandedWrap disabled
                              inherited Sort(TMethod(Compare).Code); //здесь на этапе компиляции возникает ошибка
                              Цитата Felan @
                              inherited Sort(TMethod(Compare).Code); //здесь на этапе компиляции возникает ошибка


                              проверять лень, но по идее не должно быть ошибке на этапе компиляции.. Тока в run-time av'шка какая нить возникнет.
                                Угу... возникает...
                                Ну, если сделать доступ потокобезопасный к Sort, то можно так извращьнуться :)

                                ExpandedWrap disabled
                                  unit Unit7;
                                   
                                  interface
                                   
                                  uses
                                    Contnrs;
                                   
                                  type
                                    TMyCompareFunction = function(aItem1: Pointer; aItem2: Pointer): integer of object;
                                   
                                    TMyObjectList = class(TObjectList)
                                      procedure Sort(aCompareFunction: TMyCompareFunction); reintroduce;
                                    end;
                                   
                                   
                                  implementation
                                   
                                  var
                                    vCF: TMyCompareFunction;
                                   
                                  function cmp(aItem1: Pointer; aItem2: Pointer): integer;
                                  begin
                                    Result := vCF(aItem1, aItem2 );
                                  end;
                                   
                                  { TMyObjectList }
                                   
                                  procedure TMyObjectList.Sort(aCompareFunction: TMyCompareFunction);
                                  begin
                                    vCF := aCompareFunction;
                                    inherited Sort(cmp);
                                  end;
                                   
                                  end.


                                Тогда получится что в наследнике как раз метод...
                                  Цитата DelphiLexx @
                                  я не хочу отделять ф-цию Compare от класса, мне не хотелось бы в моем классе, у которого есть метод Sort, чтобы он использовал вещи лежащие вне класса.
                                  ...не граммотно это

                                  Глупости. Так можно дойти до того, что и функции из модулей StrUtils, Math и т.п. нельзя использовать, поскольку они не принадлежат классу :)

                                  Во-первых, можно просто функции сравнения дать осмысленное название (типа CompareTMyListItems) и разместить ее в implementation рядом с твоим Sort. Ничего страшного или неграмотного в этом нет - "я так тыщу раз делал" (С)
                                  Во-вторых, функция сравнения должна быть "глобальной" по сути, а не формально. Т.е. это может быть и вложенная функция внутри самой Sort при условии, что она не будет обращаться к локальным переменным функции Sort (включая Self и его поля). Пример:
                                  ExpandedWrap disabled
                                    type
                                      TMylist = class(TList)
                                      public
                                        procedure Sort(Desc:boolean = false);overload;
                                      end;
                                    procedure tMyList.Sort(Desc:boolean = false);
                                      //вложенные функции сравнения
                                      function CompareAsc(Item1,Item2:pointer):integer;
                                      begin
                                        result:=integer(Item1)-integer(Item2);
                                      end;
                                      function CompareDesc(Item1,Item2:pointer):integer;
                                      begin
                                        result:=integer(Item2)-integer(Item1);
                                      end;
                                    begin
                                      if Desc then
                                        Sort(@CompareDesc)
                                      else
                                        Sort(@CompareAsc);
                                    end;
                                     
                                    procedure TForm1.Button1Click(Sender: TObject);
                                    var
                                      L:TMyList;
                                      S:string;
                                      i:integer;
                                    begin
                                      L:=TMyList.Create;
                                      try
                                        L.Add(pointer(2));
                                        L.Add(pointer(1));
                                        L.Add(pointer(3));
                                        L.Sort;
                                        S:='';
                                        for i:=0 to L.Count-1 do
                                          S:=S+IntTostr(integer(L[i]));
                                        L.Sort(true);
                                        S:=S+#13#10;
                                        for i:=0 to L.Count-1 do
                                          S:=S+IntTostr(integer(L[i]));
                                        ShowMessage(S);
                                      finally
                                        L.Free;
                                      end;    
                                    end;
                                  Сообщение отредактировано: leo -
                                    Felan кошмар, ужос!!!!!!!!!!!!!! У тебя же глобальная функция!!!!!!!!!!!!!

                                    Добавлено
                                    Цитата leo @
                                    то она не будет обращаться к локальным переменным функции Sort

                                    кста, немного по извращавшись с асмом можно сделать, чтоб она могла к локальным переменным обращаться.
                                      Цитата Felan @
                                      Ну, если сделать доступ потокобезопасный к Sort, то можно так извращьнуться

                                      А вот ненужные глобальные переменные ИМХО это гораздо большее извращение, чем "глобальные" функции ;) Проще скопипастить реализацию QuickSort из Classes и переопределить функцию сравнения на метод.

                                      PS: Если метод нужен только для того, чтобы добраться до некоторого св-ва TMyList, то есть вариант использовать в элементах Item ссылку на список Parent:TMyList и в функции сравнения юзать
                                      if TMyItem(Item1).Parent.FSign then ...

                                      Цитата jack128 @
                                      кста, немного по извращавшись с асмом можно сделать, чтоб она могла к локальным переменным обращаться

                                      В отношении Sort шибко сомневаюсь, т.к. она использует рекурсивные вызовы QuickSort, в которую передается не сам TList, а только массив указателей. Поэтому уже на втором уровне вложенности все локальные переменные Sort улетят далеко-далеко ;)
                                      Сообщение отредактировано: leo -
                                        Цитата leo @
                                        В отношении Sort шибко сомневаюсь, т.к. она использует рекурсивные вызовы QuickSort, в которую передается не сам TList, а только массив указателей. Поэтому уже на втором уровне вложенности все локальные переменные Sort улетят далеко-далеко ;)


                                        Ну вот такой код:

                                        ExpandedWrap disabled
                                          procedure TForm3.Test;
                                          var
                                            LocalCounter: Integer;
                                            function LocalCompare(Item1, Item2: Integer): Integer;
                                            begin
                                              Inc(LocalCounter);
                                              Inc(GlobalCounter);
                                              Result := Item1 - Item2;
                                            end;
                                          var
                                            I: Integer;
                                            L: TList;
                                          begin
                                            Randomize;
                                            GlobalCounter := 0; LocalCounter := 0;
                                            L := TList.Create;
                                            try
                                              for I := 0 to 100 - 1 do
                                                L.Add(Pointer(Random(100)));
                                              L.Sort(LocalProcCaller(@LocalCompare).Proc);  // вся магия в LocalProcCaller.  там динамически генерится код, подправляющий стек.
                                              Memo1.Lines.Clear;
                                              for I := 0 to L.Count - 1 do
                                                Memo1.Lines.Add(IntToStr(Integer(L[I])));
                                              Memo1.Lines.Add(Format('LocalCount = %d, GlobalCounter = %d', [LocalCounter, GlobalCounter])) // LocalCount всегда равен GlobalCounter.  AV нигде нет. Сортируется тоже нормально..
                                            finally
                                              L.Free;
                                            end;
                                          end;


                                        Скажу чесно сам я в асме не силен, идею почерпнул из модуля AsyncCalls.pas. Если интересно могу выложить исходники LocalProcCaller, может багу кто найдет.
                                          jack128 ААААА!!!!!!!!!! Убей меня об стенку скореее!!!!!!!!!! :)

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

                                          leo Так ты самую вкусность скрыл. Теперь извне классу не подставишь "компоратор". Если раньше можно было для любого объекта сделать функцию сравнения, передать ее в список и он бы сортировал что угодно, то теперь только то, что ты пропишешь и ничего более.
                                            Может хватит, а? А то впечатление, что здесь одни извращенцы собрались.
                                            Функция сравнения, как я уже сказал, сделана именно функцией совсем не случайно. Можно было ее сделать методом класса, но не сделали потому, что контейнер TObjectList может хранить и "чужие" объекты, у которых метода сравнения нет и сделать нельзя (о хелперах не говорю).
                                              Цитата jack128 @
                                              вся магия в LocalProcCaller. там динамически генерится код, подправляющий стек

                                              Ну ежели динамически, то конечно ;) В таком случае можно и вызов метода из функции организовать наподобии MakeObjectInstance

                                              Цитата Felan @
                                              Так ты самую вкусность скрыл. Теперь извне классу не подставишь "компоратор". Если раньше можно было для любого объекта сделать функцию сравнения, передать ее в список и он бы сортировал что угодно, то теперь только то, что ты пропишешь и ничего более

                                              "Скрыл" только для примера, по заявкам трудящихся антиглобалистов :D
                                              К тому же за счет overloaded оригинальный Sort остается - подставляй, что хочешь

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

                                              Странное объяснение ;) Значит сравнивать "несравнимые" элементы разрешили (через функцию), но иметь при этом доступ к некому объекту (владельцу функции сравнения) - ни-изя ?!
                                                Цитата leo @
                                                Значит сравнивать "несравнимые" элементы разрешили (через функцию), но иметь при этом доступ к некому объекту (владельцу функции сравнения) - ни-изя ?!

                                                А зачем и с какой целью? Тебе даны две сущности - их и сравни. Заодно при смене контейнера функцию менять не надо, она уже есть.
                                                Каким образом результат сравнения двух сущностей может зависеть от экземпляра контейнера, в котором они содержатся?
                                                  Цитата Romkin @
                                                  Каким образом результат сравнения двух сущностей может зависеть от экземпляра контейнера, в котором они содержатся?

                                                  э-э-э. TStrings.CompareStrings например.
                                                    Цитата jack128 @
                                                    э-э-э. TStrings.CompareStrings например.

                                                    И шо? Там строки, все сразу понятно. И от контейнера тоже не зависит. Добавь к этому, что TStrings - абстрактный класс, ты обязан написать потомка.
                                                    А вот TStringList.CustomSort опять использует функцию, экземпляр в которую передается только потому, что неизвестно, какой элемент ты хочешь сравнивать, саму строку, или объект, и даются индексы. И для реализации сравнения не нужно писать потомка.
                                                    Это удобно и разумно. И криминала здесь никакого нет. Вообще.
                                                      Цитата Romkin @
                                                      И от контейнера тоже не зависит.

                                                      ну как же - смотрим его наследника, TStringLIst и что мы видим ?? Функция сравнения использует данные класса.
                                                        Цитата jack128 @
                                                        ну как же - смотрим его наследника, TStringLIst и что мы видим ?? Функция сравнения использует данные класса.

                                                        Хм. Действительно. Выбор нужной функции для сравнения.
                                                        Но абсолютно не мешает подать соответствующую функцию compare в Sort. Leo чуть выше практически это и сделал. Так что криминала все равно нет.
                                                        А вот если бы TList использовал свою виртуальную функцию, тебе пришлось бы на каждый чих писать его наследника.
                                                          Цитата Romkin @
                                                          А вот если бы TList использовал свою виртуальную функцию,

                                                          а никто этого и не предлагает. ПРедлагают чтоб List.Sort принемал не функцию, а метод.
                                                            Цитата Romkin @
                                                            Каким образом результат сравнения двух сущностей может зависеть от экземпляра контейнера, в котором они содержатся?

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

                                                              А это не крайность, это вопрос удобства. В данном случае метод просто унаследован от TList, а там чаше всего требование именно метода ограничивает, мало ли на что я там ссылки хранить буду. А мотивов переделывать Sort на получающий метод я не вижу.
                                                                Цитата 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 есть виртуальные классовые методы??
                                                                                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                          0 пользователей:


                                                                                          Рейтинг@Mail.ru
                                                                                          [ Script execution time: 0,1047 ]   [ 15 queries used ]   [ Generated: 18.06.21, 00:04 GMT ]