
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[216.73.216.3] |
![]() |
|
Страницы: (3) 1 2 [3] все ( Перейти к последнему сообщению ) |
Сообщ.
#31
,
|
|
|
Во-первых, не переделывать, a overload-ить для удобства использования. Во-вторых, мотив прозвучал "во первЫх строках" сей темы - народ с подачи самого Борланда привык к классам и методам и соотв-но требует "хлеба и зрелищ" ![]() ![]() |
Сообщ.
#32
,
|
|
|
Вообщем, моя точка такова, сделано не совсем у Borland'а не совсем правильно, нужно было реализовать два варианта когда compare должна быть методом и когда должна быть общей (глобальной) и не было бы проблем.
|
Сообщ.
#33
,
|
|
|
Цитата Romkin @ В данном случае метод просто унаследован от TList, а там чаше всего требование именно метода ограничивает, мало ли на что я там ссылки хранить буду Да ниче не ограничивает. Как тут уже сказали, этот метод не обязательно должен принадлежать контейнеру. Он может принадлежать элементу. А элементы могут быть разными, но реализовывать один интерфейс для сравнения, если по смыслу задачи это надо. Собственно пофиг че пользовать, метод или функцию. Просто в свете современных веяний, и того, что в новых языках и т.п. и т.д. вообще не может быть никаких функций не принадлежащих никакому классу. И, лично я, считаю, что это правильно. Раз идеология с процедурной сменилась на объектную, нефиг за собой артефакты таскать. И с точки зрения цельности абстракции никому не принадлежащая функция как-то странно выглядит... Вобщем, ИМХО, это пережиток. Надо все-таки в сторону методов смотреть. |
Сообщ.
#34
,
|
|
|
Цитата Felan @ Как тут уже сказали, этот метод не обязательно должен принадлежать контейнеру. Он может принадлежать элементу. А элементы могут быть разными, но реализовывать один интерфейс для сравнения, если по смыслу задачи это надо. Цитата Romkin @ Можно было ее сделать методом класса, но не сделали потому, что контейнер TObjectList может хранить и "чужие" объекты, у которых метода сравнения нет и сделать нельзя (о хелперах не говорю). Зачем писать лишнее? Все сделано грамотно. |
Сообщ.
#35
,
|
|
|
Цитата Felan @ Раз идеология с процедурной сменилась на объектную, нефиг за собой артефакты таскать. И с точки зрения цельности абстракции никому не принадлежащая функция как-то странно выглядит... Полностью с тобой согласен |
Сообщ.
#36
,
|
|
|
Ладно, все равно уже наоффтопили...
Цитата Felan @ Собственно пофиг че пользовать, метод или функцию. Просто в свете современных веяний, и того, что в новых языках и т.п. и т.д. вообще не может быть никаких функций не принадлежащих никакому классу. И, лично я, считаю, что это правильно. А я в этом не уверен. Возьмем Java или C#. На 100% объектный? Многим покажется что да. Но как тогда объяснить такое загадочное явление, как статические методы, которые ни к объектам ни к классам никакого отношения вообще не имеют, если разобраться? А ведь они введены как раз из-за того, что в 100% объектном языке нет и не может быть бесхозных процедур/функций. Просто произошла подмена понятий и класс взял на себя функцию пространства имен, которую в Delphi традиционно выполняет юнит. Добавлено Кстати, а как быть, когда мне нужна сортировка по разным критериям одновременно? У какого класса делать методы сравнения? У контейнера или элементов? Если первое, то в классе контейнере в общем случае невозможно учесть все типы элементов, которые могут в нем содержаться. Если второе, то в классе элементов невозможно учесть все критерии, по которым я захочу их сравнивать. Если делать гибко, то ничего лучше внешней функции не придумаешь. Ну, разве что классы-сортировщики с единственным статическим методом Compare, но эта "красота" за уши притянута, а почему - я писал выше. |
Сообщ.
#37
,
|
|
|
Ins, хорошее замечание
![]() Действительно, если объявить компаратор как метод, и если у меня нет класса (например, я использую класс списка в простой процедуре и мне надо его отсортировать), то я вынужден писать такое: ![]() ![]() type TDummy = class class function Compare(Item1, Item2: Pointer): Integer; end; class function TDummy.Compare(Item1, Item2: Pointer): Integer; begin // ... end; Вместо: ![]() ![]() function Compare( { List: TSomeList; } Item1, Item2: Pointer): Integer; begin // ... end; Оба варианта (метод/функция) являются удобными в каких-то отдельных случаях. И нет универсально удобного способа. Если отбросить в сторону стилевые предпочения (и охота вам проблемы на пустом месте создавать), то самый важный момент связан с тем, можете ли вы пердать внешние данные в компаратор или нет. Т.е. с передачей user-data. Если компаратор является методом, то все дополнительные данные могут передаваться через объект - в конце концов метод это же код + данные. Если компаратор является функцией, то нет уже умалчиваемого способа задания внешних данных. Обычно такую передачу делают через обобщённый user-param типа Pointer или Cardinal. Через него можно передать любые данные, какие вам надо. Например, как это сделано в TStringList: ![]() ![]() TStringListSortCompare = function(List: TStringList; Index1, Index2: Integer): Integer; Окей, компаратор TObjectList не имеет user-param-а. Почему? Хороший вопрос ![]() ![]() ![]() 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; |
Сообщ.
#38
,
|
|
|
Цитата --Ins-- @ А я в этом не уверен. Возьмем Java или C#. На 100% объектный? Многим покажется что да. Но как тогда объяснить такое загадочное явление, как статические методы, которые ни к объектам ни к классам никакого отношения вообще не имеют, если разобраться? Если разобраться, то методы относятся к экземпляру класса, а статические методы к классу. Класс это абстракция. Основное понятие ООП. Плюс этому то, что говорил CodeMonkey про параметризацию компоратора. А в отдельный класс эти методы выносить или для каждого свой, или еще как-то это вопрос дизайна, который каждый для себя решает сам. Нет понятия правильного/неправильного дизайна. Есть лучший/худший, и многие "законодатели мод" считают что объектный дизайн лучше, чем процедурный. ![]() |
Сообщ.
#39
,
|
|
|
Цитата Felan @ а статические методы к классу. А ты не путаешь class methods Delphi со static-методами Джавы и Шарпа? Эт не одно и то же ![]() |
Сообщ.
#40
,
|
|
|
Нет. Не путаю.
Это просто абстракция, но это средства упорядочивания логической структуры. Покажи мне пример, как вызвать статический метод джавы или шарпа без имени класса. Без извращений с отражениями. Если сможешь, посыплюсь пеплом и признаю твою правоту, иначе ты не прав. |
Сообщ.
#41
,
|
|
|
Felan, ты не понял. Смотри, классовый метод в Delphi действительно работает с классом. А статик-метод в Java - нет. Класс для него является лишь простанством имен, подобно тому, как для обычной процедуры пространством имен в Delphi является юнит. Так в чем же принципиальная разница между статик-методом и функцией/процедурой? В том, что для вызова статик-метода пространство имен указывать обязательно, а для обычной процедуры - нет?
![]() Добавлено Вообще, почему в TList параметр функция, а не метод - понятно. TList - это контейнер произвольных данных, не обязательно объектов, так зачем же вешать объектную оболочку над необъектной сущностью. Да и исторически так сложилось. Почему не сделали overload-метод у TObjectList, скажем? Да фиг его знает, не посчитали необходимым. Но разве тяжело ввести его самому? Если пишешь наследника - просто объявляешь свой метод, если используешь сам TObjectList - хелпер в руки. ![]() |
Сообщ.
#42
,
|
|
|
Цитата --Ins-- @ Так это чаще всего преимущество. Не нужно ради одной подпрограммы городить целый класс и каждый раз его указывать. + 1. Тот же Delphi например. Зачем надо было RaiseOuterException делать простым статическим методом класса? Теперь вместо компактного (возможного) варианта: ![]() ![]() try ... except on E: Exception do begin ... raiseOuter(Exception.Create(...)); end; end; Нужно писать: ![]() ![]() try ... except on E: Exception do begin ... Exception.RaiseOuterException(Exception.Create(...)); end; end; А чего стоит ![]() ![]() TCharacter = class sealed состоящий только из статических классовых методов! Причём, чтобы не корячится каждый раз с TCharacter.ToLower, в этом же модуле введены процедуры-переходники. Которые ровным счётом ничего не делают, кроме как вызывают методы TCharacter. Ужас. Не иначе как для совместимости с ???... не знаю, .NET, может быть. Скоро Integer станет sealed-классом со статическими операторами плюс и минус ![]() Цитата --Ins-- @ хелпер в руки Да-да-да, отличная вещь! ![]() |
Сообщ.
#43
,
|
|
|
Цитата --Ins-- @ Felan, ты не понял. Смотри, классовый метод в Delphi действительно работает с классом. А статик-метод в Java - нет. Класс для него является лишь простанством имен, подобно тому, как для обычной процедуры пространством имен в Delphi является юнит. Так в чем же принципиальная разница между статик-методом и функцией/процедурой? В том, что для вызова статик-метода пространство имен указывать обязательно, а для обычной процедуры - нет? ![]() Это ты не понял. ![]() Да, "...класс для него лишь пространство имен..." и это позволяет более правильно и строго следить за структурой проекта, областями видимости и т.п. Принципиальной разницы нет. Так же как ее нет в итоге между программой написанной на разных языках (не будем разводить флейм про скорость и подобное). Еще раз говорю, это всего лишь средство организации абстракций из которых состоит проект. И сделано это для того, что бы не использовать одновременно две парадигмы, процедурную и объектную. С точки зрения процедурной парадигмы - ты прав. С точки зрения объектно-ориентированной - я прав. Остается выяснить какая парадигма правильная ![]() ![]() ![]() Но мы же не будем этим бредом заниматься? Лично мне нравится объектная. Она мне удобнее. ![]() ЗЫЖ Предлагаю мировую. А то это никогда не кончится ![]() |
![]() |
Сообщ.
#44
,
|
|
Цитата Felan @ Принципиальной разницы нет в Java есть виртуальные классовые методы?? |