Форум: "Прочее";
Текущий архив: 2007.04.22;
Скачать: [xml.tar.bz2];
ВнизВот завел себе блог Найти похожие ветки
← →
GrayFace © (2007-03-15 17:17) [240]euru © (13.03.07 16:38) [225]
Т.е. добавление полей в хелперы сильно увеличивает громоздкость реализации по сравнению с реализацией хелперов только с методами? Почему?
Хэлпер - это просто сборище функций, тут и реализовывать-то нечего (за исключением добавления синтаксиса)
Пусть в хелперах будут поля, у класса будет некий объем памяти, отведенный под хелперы. Дальше надо каждому хелперу дать смещение его данных относительно начала этого объема.
- Если это зашить в код, то сутуация: 2 пакета, в обоих по хелперу к одному и тому же классу. Оба пакета знают только о своих хелперах, значит у обоих смещение данных хелпера будет 0.
- Значит надо создавать переменную со смещением хелпера, при компиляции и дин. загрузке пакета ее заполнять и при каждом вызове метода хелпера к ней обращаться.
Теперь как можно добавить сам объем.
- Для каждого класса нужна будет переменная с размером этого блока. Опять же должна будет зполняться при динамической зарузке или компилянии программы.
Теперь возникают проблемы с самим заполнением этих переменных. Хотя вроде решаемо, придется менять vmt*, менять NewInstance, InitInstance, но вроде возможно.
Но виртуальные функции переопределять хелперам уж точно не получится, применение хелперов по-прежнему будет редким, соответственно возникает вопрос - нафига?
← →
euru © (2007-03-16 01:22) [241]Я попробую представить эту самую цепочку, в которой может потеряться информация о хелпере. Сразу прошу меня извинить, я уже давно не писал на Delphi, поэтому в коде могут быть ошибки.
1. Создадим модуль, содержащий класс, к которому в дальнейшем присоединим хелпер.unit u1;
interface
type
TA = class
end;
implementation
end.
2. Создадим модуль, содержащий хелпер к этому классу.unit u2;
interface
uses u1;
type
TB = class helper for TA
Field: Integer;
procedure DoWork();
end;
implementation
end.
3. Создадим модуль, использующий класс с хелпером.unit u3;
interface
uses u1, u2;
procedure SetField(a: TA; value: Integer);
implementation
procedure SetField(a: TA; value: Integer);
begin
a.Field := value;
end;
end.
Теперь напишем программу, в которой якобы может возникнуть коллизия.program p1;
uses u1, u3;
var a: TA;
begin
a := TA.Create();
SetField(a, 5);
end;
Модуль u2, содержащий хелпер, в программе необъявлен. Но это не помешает компилятору учесть наличие хелпера в классе, потому что его присутсятвие определяется косвенно через модуль u3, в котором есть ссылка модуль u2, содержащий хелпер.
← →
euru © (2007-03-16 01:35) [242]
> GrayFace © (15.03.07 17:17) [240]
Соглашусь, что реализация хелперов с полями будет сложнее реализации без них. Правда, пока не уверен, что она будет выглядить так громоздко.
Но пока меня интересует другой вопрос. Возможна ли в принципе реализация хелперов с полями?
> Но виртуальные функции переопределять хелперам уж точно
> не получится
Однозначно?
← →
jack128 © (2007-03-16 01:52) [243]euru © (16.03.07 1:22) [241]
Гм. Такое очущение, что ты не читал, то что написал vuk и я. Пока дело какается монолитной программы - вопросов нету. Проблемы возникнут, когда используются ран тайм пакеты.
← →
GrayFace © (2007-03-16 16:22) [244]euru © (16.03.07 1:35) [242]
Соглашусь, что реализация хелперов с полями будет сложнее реализации без них. Правда, пока не уверен, что она будет выглядить так громоздко.
А я уверен, что она будет выглядеть более громоздко.
← →
Суслик © (2007-03-16 16:34) [245]
> [243] jack128 © (16.03.07 01:52)
> euru © (16.03.07 1:22) [241]
> Гм. Такое очущение, что ты не читал, то что написал vuk
> и я. Пока дело какается монолитной программы - вопросов
> нету. Проблемы возникнут, когда используются ран тайм пакеты.
уж прости :) сам люблю опечатки, но у тебя получилось офигительней моих в 100 раз :)
← →
jack128 © (2007-03-16 21:15) [246]Суслик © (16.03.07 16:34) [245]
но у тебя получилось офигительней моих в 100 раз :)
Ну дык! Стараемся. Растём над собой, так сказать ;-)
← →
euru © (2007-03-19 02:26) [247]
> jack128 © (16.03.07 01:52) [243]
> Такое очущение, что ты не читал, то что написал vuk и я.
Почему не читал? Читал. Но ведь это просто предположение, ничем не подтверждённое. С таким же успехом я могу утверждать, что не будет никаких проблем с использованием хелперов в динамически загруженных пакетах. В пользу своего утверждения я привёл пример. В ответ не получил ни указаний ошибок в моих рассуждениях, ни контрпримеров, доказывающих ваши утверждения.
> vuk © (15.03.07 00:28) [234]
> А если так: экземпляр по цепочке вызовов передается невесть
> куда в пакет (например динамически загруженный) и уже там
> на него навешивается хелпер. Что делать-то?
Насколько я понимаю, может быть две ситуации.
1. В программе создаётся хелпер для класса, объявленного в пакете. Использование объектов такого класса с хелпером в самой программе проблем не вызовет (см. [241]). Передача таких объектов в пакет тоже ни к чему криминальному не приведёт. В пакет передастся только та часть объекта, которая используется в пакете. А как с ней работать, пакет знает.
2. Хелпер для типа, используемого в программе, создаётся в пакете. Если я не ошибаюсь, для организации взаимодействия с пакетом создаётся модуль, в котором описывается интерфейс этого пакета. Если описание сделано корректно, то компилятору будет известна информация о наличие хелпера в пакете, и он учтёт её при создании объектов.
> А скорость доступа к данным является аргументом?
Нет. К языку программирования он никакого отношения не имеет.
> jack128 © (15.03.07 01:46) [235]
> затем, что раз есть в хелпере есть поле, то оно должно быть
> во всех классах. В том числе и тех, что были созданы кодом
> внутри пакета.
А если я перефразирую так: раз в потомке есть поле (класс с хелпером фактически является потомком оригинального класса), то оно должно быть во всех классах. В том числе и в его предках (оригинальный класс в пакете фактически является предком для класса с хелпером в программе).
Это будет правильным утверждением?
← →
euru © (2007-03-19 02:46) [248]
> GrayFace © (15.03.07 17:17) [240]
А если так.
Класс знает список всех добавленных когда-либо к нему хелперов. При создании объекта у него заполняется список только тех хелперов, которые реально использовались для этого объекта.
Теперь обращение к элементам хелпера объекта приведёт к следующим шагам:
1. Поиск идентификатора хелпера среди всех хелперов класса.
2. Поиск найденного идентификатора хелпера среди хелперов объекта.
3. Если такой идентификатор у объекта не найден, то выдать сообщение об ошибке.
4. Если хелпер у объекта есть, то взять идентификатор этого хелпера в объекте.
5. Адрес к данным объекта, добавленным хелпером, найти в таблице на пересечении идентификаторов хелпера класса и объекта.
> Но виртуальные функции переопределять хелперам уж точно
> не получится
А, например, подменить в vmt адрес виртуальной функции класса адресом функции хелпера?
← →
GrayFace © (2007-03-19 20:32) [249]euru © (19.03.07 2:26) [247]
В пользу своего утверждения я привёл пример.
Где??
euru © (19.03.07 2:26) [247]
класс с хелпером фактически является потомком оригинального класса
Теперь все ясно, ты ничего не понял о хелперах. Хелпер динамически подключается к классу, в том числе к классу из пакета. Пакет не будет сам по себе создавать объекты "класса с хелпером".
euru © (19.03.07 2:46) [248]
3. Если такой идентификатор у объекта не найден, то выдать сообщение об ошибке.
Т.е. при любой попытке использовать хелпер будет ошибка? А то кто ж добавит его идентификатор к хелперам объекта?
euru © (19.03.07 2:46) [248]
5. Адрес к данным объекта, добавленным хелпером, найти в таблице на пересечении идентификаторов хелпера класса и объекта.
3D таблица со всеми хелперами, классами и объектами? :)))
euru © (19.03.07 2:46) [248]
А, например, подменить в vmt адрес виртуальной функции класса адресом функции хелпера?
А как определить, кто из хелперов "главнее"?
← →
jack128 © (2007-03-20 01:56) [250]euru © (19.03.07 2:26) [247]
раз в потомке есть поле (класс с хелпером фактически является потомком оригинального класса
нет, класс с хелпером - это не потомок класса.
euru © (19.03.07 2:26) [247]
раз в потомке есть поле , то оно должно быть во всех классах.
Что за бред???
Вообще ПРИНЦИПИАЛЬНО реализовать, то что ты хочешь - можно. Но на практиче - это с одной стороны будет весьма сложно для разработчиков компилятора, с другой - доступ к этим полям будет весьма и весьма тормознутым. Короче - нафиг надо. Кому это реально нужно, те без проблем смогут сами все это реализовать, благо в дельфе все для этого есть.
← →
euru © (2007-03-20 15:26) [251]
> GrayFace © (19.03.07 20:32) [249]
> Где??
Здесь - [241].
> Теперь все ясно, ты ничего не понял о хелперах.
О каких хелперах? Которые в Delphi? Так о них вроде бы уже всё выяснили. Я же о других хелперах говорю. Тех, которые добавляют к классу не только методы, но и поля. А это явно не просто динамическая привязка методов хелпера к классу.
> Пакет не будет сам по себе создавать объекты "класса с хелпером".
А вот товарищи vuk и jack128 считают иначе - см. [234] и [235].
> Т.е. при любой попытке использовать хелпер будет ошибка?
> А то кто ж добавит его идентификатор к хелперам объекта?
Компилятор обладает всей необходимой информацией, которая позволит ему правильно инициализировать список хелперов объекта при его создании.
> 3D таблица со всеми хелперами, классами и объектами? :)))
А 2D-таблица vmt со всеми классами и методами улыбки не вызывает?
> А как определить, кто из хелперов "главнее"?
А зачем? Совпадение сигнатуры методов вызовет сообщение об ошибке ещё во время компиляции.
--------------------------------------------------------------------
> jack128 © (20.03.07 01:56) [250]
> нет, класс с хелпером - это не потомок класса.
С точки зрения разработчика - не потомок. Программист продолжает использовать тот же класс, что и раньше. Просто у класса появились новые поля и методы. С точки зрения компилятора - потомок. Новую функциональность нельзя просто механически приписать к текущему классу. Хотя бы потому, что в разных модулях могут объявляться разные хелперы к одному и тому же классу. И для контроля правильности их использования компилятору нужно будет как-то их различать. А это можно сделать, создав, например, потомков (недоступных разработчику) от оригинального класса для всех используемых вариантов с хелперами.
> Что за бред???
А требование наличия хелперов во всех пакетах, даже там, где они изначально не были предусмотрены, не бред?
> Вообще ПРИНЦИПИАЛЬНО реализовать, то что ты хочешь - можно.
> Но на практиче - это с одной стороны будет весьма сложно
> для разработчиков компилятора, с другой - доступ к этим
> полям будет весьма и весьма тормознутым. Короче - нафиг
> надо.
Чем-то напоминает утверждения 15-20-летней давности о необходимости в языках средств ООП.
> Кому это реально нужно, те без проблем смогут сами все это
> реализовать, благо в дельфе все для этого есть.
А вот можно увидеть пример текущей дельфийской реализации хелперов в Delphi 7 и ниже средствами самого языка? И если это действительно можно, то зачем тогда они были введены?
← →
GrayFace © (2007-03-23 21:57) [252]euru © (20.03.07 15:26) [251]
Здесь - [241].
Это ж не кусок реализации. Даже не пример когда это нужно.
euru © (20.03.07 15:26) [251]
А вот товарищи vuk и jack128 считают иначе - см. [234] и [235].
Нет, так же.
jack128 © (20.03.07 1:56) [250]
Но на практиче - это с одной стороны будет весьма сложно для разработчиков компилятора, с другой - доступ к этим полям будет весьма и весьма тормознутым.
Думаю, можно сделать и без особых временных затрат на доступ, но проблем по горло.
euru © (20.03.07 15:26) [251]
А 2D-таблица vmt со всеми классами и методами улыбки не вызывает?
Конечно нет. Объектов могут быть тысячи.
euru © (20.03.07 15:26) [251]
А зачем? Совпадение сигнатуры методов вызовет сообщение об ошибке ещё во время компиляции.
Пакеты компилируются отдельно друг от друга и могут подключаться к программе динамически.
euru © (20.03.07 15:26) [251]
С точки зрения разработчика - не потомок. Программист продолжает использовать тот же класс, что и раньше. Просто у класса появились новые поля и методы. С точки зрения компилятора - потомок. Новую функциональность нельзя просто механически приписать к текущему классу. Хотя бы потому, что в разных модулях могут объявляться разные хелперы к одному и тому же классу. И для контроля правильности их использования компилятору нужно будет как-то их различать. А это можно сделать, создав, например, потомков (недоступных разработчику) от оригинального класса для всех используемых вариантов с хелперами.
Ну вот ты сам сказал, что хелперы с полями невозможны (хотя это не совсем так) или будут непонятно чем. См. то что выделено жирным. Объект может создаваться в одном пакете, а в другом - использоваться хелпер к такому же классу. В твоей схеме в этом случае велетит ошибка? Тогда скажи, зачем программист будет писать хелперы к своим классам, вместо того чтобы создать потомка? Ведь для чужих пакетов он хелперов написать не сможет.
← →
euru © (2007-03-25 03:39) [253]
> GrayFace © (23.03.07 21:57) [252]
> Тогда скажи, зачем программист будет писать хелперы к своим
> классам, вместо того чтобы создать потомка?
Думаю, это основной вопрос.
С моей точки зрения, наследование -- это экстенсивный путь развития объектной модели. В общем случае добавление в ней новых свойств требует появление новых классов-потомков, которые бы эти свойства реализовали. При этом чем более древовидна модель, тем больше появится потомков, реализующих эти свойства. Для избежания возникающего при этом дублирования кода часто приходится пересматривать иерархию и либо добавлять новые свойства в классы-предки, либо встраивать в иерархию промежуточные классы. В первом случае появляются монстроидальные классы (типа TControl), которые содержат в себе множество бесполезной для их уровня информации. Во втором случае появляются лишние абстрактные классы, также не имеющие пользы и только загромождающие иерархию.
Теоретически (по крайней мере, о реализации я не слышал) существует также интенсивный путь развития модели. По мере появления у объектной модели новых свойств они оформляются в виде отдельных специальных классов, которые по мере необходимости присоединяются к основным классам на любом уровне иерархии, обеспечивая требуемую функциональность для объектов этого класса и его потомков.
Примеры применения (на примере VCL) таких классов я уже приводил выше, но повторю их ещё раз:
1. Поле PasswordChar в классе TEdit. Очень редко используемое поле. Вынеся его во вспомогательный класс можно было бы добавлять это поле (и соответствующее поведение) только к тем объектам TEdit, которым оно действительно нужно.
2. Свойство Dockable у класса TControl. Тоже не для всех контролов и не во всех проектах используется. Также можно вынести в отдельный класс и подключать по мере необходимости.
3. Дублирование обычных контролов и DB-контролов. DB-функциональность можно было бы вынести в отдельный вспомогательный класс и подключать его к нужным обычным контролам.
Фактически Borland реализовала в хелперах второй метод. Но, ограничив хелперы только наличием в них методов, существенно ограничил область их применения, сделав их в большинстве случаев бесполезными.
Поэтому программисты будут продолжать использовать обычное наследование и удивляться, зачем Borland ввела в язык очередной бесполезный костыль (который, скорее всего, со временем также может увеличить разгребаемую сейчас кучу).
P.S.: Кстати, кроме наследования (вертикального связывания классов) существует ещё и горизонтальное связывание, реализуемое в аспектно-ориентированных языках. Спасибо vuk"у, который в соё время дал ссылки на такие языки. В сравнении с этими способами связывания хелперы можно назвать внутренним связыванием, реализующим саморазвитие классов.
Страницы: 1 2 3 4 5 6 7 вся ветка
Форум: "Прочее";
Текущий архив: 2007.04.22;
Скачать: [xml.tar.bz2];
Память: 1.04 MB
Время: 0.075 c