На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное DigiMania 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 -
    Pascal - как англ. язык, I Love You - слова местами не переставишь, всё прямо и понятно. С++ - как русский язык, Я люблю тебя, тебя люблю я, люблю я тебя - уйма вариантов с кучей интонаций. Asm - как китайский язык - одна черточка не в том месте и ты уже не признался в любви, а послал кого-то на йух
      функция <> метод
      В споре никогда не рождается истина.
        Цитата Domino @
        функция <> метод

        Ну так как передать, не ужели глобальную ф-цию заводить?
        Pascal - как англ. язык, I Love You - слова местами не переставишь, всё прямо и понятно. С++ - как русский язык, Я люблю тебя, тебя люблю я, люблю я тебя - уйма вариантов с кучей интонаций. Asm - как китайский язык - одна черточка не в том месте и ты уже не признался в любви, а послал кого-то на йух
          Так у тебя Sort че принимает то? И че ты туда передаешь?

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


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

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


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


            Что значит глобальной?
            Все фотографии-обои Виталия Невзорова одним файлом. 3Гб.
            http://www.almar.su/nevzorov/photo.zip
            Если с вопросами все будут посылать в гугль - откуда в нём возьмутся ответы?
              Цитата Felan @
              Она у тебя принимает функцию, а не метод. Ты же наследника делаешь, ну сделай, что бы он у тебя метод принимал, а предку функцию сделай, которая этот метод вызывать будет.

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

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

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

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

              Как что, глобальная ф-ция - это ф-ция объявленная в секции interface и реализованная в секции implementation'a и не являющаяся методом какого-либо класса.
              Pascal - как англ. язык, I Love You - слова местами не переставишь, всё прямо и понятно. С++ - как русский язык, Я люблю тебя, тебя люблю я, люблю я тебя - уйма вариантов с кучей интонаций. Asm - как китайский язык - одна черточка не в том месте и ты уже не признался в любви, а послал кого-то на йух
                Объяви ее только в implementation.
                Beware the wild rabbit.
                  Цитата Romkin @
                  Объяви ее только в implementation.

                  Не хотел бы я использовать в Sort, то что не принадлежит классу, не граммотно это.
                  Pascal - как англ. язык, I Love You - слова местами не переставишь, всё прямо и понятно. С++ - как русский язык, Я люблю тебя, тебя люблю я, люблю я тебя - уйма вариантов с кучей интонаций. Asm - как китайский язык - одна черточка не в том месте и ты уже не признался в любви, а послал кого-то на йух
                    Цитата DelphiLexx @
                    Не хотел бы я использовать в Sort, то что не принадлежит классу, не граммотно это.

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


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

                        Либо второй вариант - принять, что не класс является единицей реализации, а и модуль, в котором он описан.
                        Все фотографии-обои Виталия Невзорова одним файлом. 3Гб.
                        http://www.almar.su/nevzorov/photo.zip
                        Если с вопросами все будут посылать в гугль - откуда в нём возьмутся ответы?
                          Цитата Domino @
                          Абсолютно согласен с этим утверждением.

                          И зря. Какое отношение имеет оператор сравнения к контейнеру?!
                          Beware the wild rabbit.
                            Цитата 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 может хранить и "чужие" объекты, у которых метода сравнения нет и сделать нельзя (о хелперах не говорю).
                                            Beware the wild rabbit.
                                              Цитата jack128 @
                                              вся магия в LocalProcCaller. там динамически генерится код, подправляющий стек

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

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

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

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

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

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

                                                  э-э-э. TStrings.CompareStrings например.
                                                  Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                                    Цитата jack128 @
                                                    э-э-э. TStrings.CompareStrings например.

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

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

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

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

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

                                                              А это не крайность, это вопрос удобства. В данном случае метод просто унаследован от TList, а там чаше всего требование именно метода ограничивает, мало ли на что я там ссылки хранить буду. А мотивов переделывать Sort на получающий метод я не вижу.
                                                              Beware the wild rabbit.
                                                                Цитата Romkin @
                                                                А мотивов переделывать Sort на получающий метод я не вижу

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

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

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

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

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


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

                                                                        Полностью с тобой согласен
                                                                        Pascal - как англ. язык, I Love You - слова местами не переставишь, всё прямо и понятно. С++ - как русский язык, Я люблю тебя, тебя люблю я, люблю я тебя - уйма вариантов с кучей интонаций. Asm - как китайский язык - одна черточка не в том месте и ты уже не признался в любви, а послал кого-то на йух
                                                                          Ладно, все равно уже наоффтопили...

                                                                          Цитата 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;
                                                                            Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
                                                                              Цитата --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-- @
                                                                                      хелпер в руки

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

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

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

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

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

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

                                                                                        :)

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

                                                                                          в Java есть виртуальные классовые методы??
                                                                                          Не каждая серая масса имеет что-то общее с мозгом (с) Станислав Ежи Лец
                                                                                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                                          0 пользователей:


                                                                                          Рейтинг@Mail.ru
                                                                                          [ Script Execution time: 0,3771 ]   [ 16 queries used ]   [ Generated: 19.03.19, 10:10 GMT ]