Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];

Вниз

И снова хелперы :)   Найти похожие ветки 

 
Суслик ©   (2007-04-11 00:57) [0]

Уважаемые, противники нововведний в дельфи.

Почитайте http://timokhov.blogspot.com/2007/04/blog-post.html
См. ссылку в посте.

ИМХО неплохо можно использовать новые фишки в языке. Разве нет?


 
_Аноним   (2007-04-11 10:17) [1]

Это в 2007 будет?


 
Игорь Шевченко ©   (2007-04-11 10:35) [2]


> См. ссылку в посте.


Нет, чтоб перевести на понятный язык


 
Чапаев ©   (2007-04-11 10:36) [3]

Капец... Давать ссылку на ссылку...


 
_Аноним   (2007-04-11 10:38) [4]


> Чапаев ©  

Чтобы довести ситуацию до абсурда, можно знакомым давать эту ссылку:
http://delphimaster.net/view/15-1176238641/
"посмотрите, какие нововведения в delphi"
:-)


 
Суслик ©   (2007-04-11 10:47) [5]


>  [2] Игорь Шевченко ©   (11.04.07 10:35)
> > См. ссылку в посте.
> Нет, чтоб перевести на понятный язык


Ты про то, чтобы перевести?
Я подумаю об этом :)


>  [1] _Аноним   (11.04.07 10:17)
> Это в 2007 будет?


Вообще это все должно быть и БДС2006 (многое из описанного я использую в БДС2006). Другой вопрос, что в Д2007 это может постабильней работать. Это я точно не знаю, т.к. качеством работы итераторов доволен и в БДС2006. Как минимум ни одной ошибки не видел.


 
Суслик ©   (2007-04-11 10:48) [6]


> [3] Чапаев ©   (11.04.07 10:36)
> Капец... Давать ссылку на ссылку...

ну себя тоже хочется попиарить :)


 
Чапаев ©   (2007-04-11 10:49) [7]

> [6] Суслик ©   (11.04.07 10:48)
Тю... Так написал бы: подробности смотри в моём блоге по адресу "...". А то поди догадайся, что timokhov -- это ты... %-)


 
_Аноним   (2007-04-11 10:52) [8]


> Суслик ©  

Пищи еще)
Я с каждого раза что-то новое узнаЮ  :-)
вот про for in узнал
точнее, для перечислимых типов уже знал, а то что и по стринг листу работает - это новость

А читать "what"s new" при выходе новой версии - это не по нашему)


 
Суслик ©   (2007-04-11 10:54) [9]


> А читать "what"s new" при выходе новой версии - это не по
> нашему)

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

правда, до указанного извращения я сам не додумался пока.

в what news можно только базовые новости почитать.

имхо


 
euru ©   (2007-04-11 12:54) [10]

Ну да. Как только в хелпере понадобилось хранить состояние класса, а в самом классе "лишних" полей не нашлось, пришлось городить интерфейс и реализующий его класс. Хотя с этим вполне мог бы справиться сам компилятор.

Гипотетический пример:
TStringsEnumerator = class helper for TStrings
private
  FIndex: Integer;
  function GetCurrent(): string;
public
  function GetEnumerator(): TStrings;
  function MoveNext(): Boolean;
  property Current: string read GetString;
end;

function TStringsEnumerator.GetCurrent(): string;
begin
  Result := Items[FIndex];
end;

function TStringsEnumerator.GetEnumerator(): TStrings;
begin;
  FIndex := -1;
  Result := Self;
end;
 
functions TStringsEnumerator.MoveNext(): Boolean;
begin
  inc(FIndex);
  Result := FIndex < Count;
end;


Неужели компилятор не смог бы, встретив такой код, сделать корректную компиляцию?


 
Суслик ©   (2007-04-11 13:24) [11]


>  [10] euru ©   (11.04.07 12:54

ты все о своем :)


 
MBo ©   (2007-04-11 13:37) [12]

>euru
Где хранится дополнительное поле?


 
euru ©   (2007-04-11 15:03) [13]


> Суслик ©   (11.04.07 13:24) [11]
> ты все о своем :)
Ну так видно же невооружённым глазом недоделанность хелперов. А в статье виден результат этой недоделанности. Весь код, который там нагромоздили только для того, чтобы сохранить текущую итерацию, мог бы с успехом сделать компилятор, и сделать это, я думаю, гораздо эффективнее.

А если учесть и другие несуразности, возникшие с вводом в язык новых понятий (о них я писал в [41] в http://delphimaster.net/view/15-1176238641/), то у меня возникают вопросы о квалифицированности разработчиков языка либо об их отношению к языку.


> MBo ©   (11.04.07 13:37) [12]
> Где хранится дополнительное поле?
Там же, где и остальные поля класса. Компилятор-то во время компиляции обладает информацией о наличии у класса хелперов и, соответственно, может учесть при выделении памяти имеющиеся в хелпере поля.


 
oxffff ©   (2007-04-11 15:18) [14]


> euru ©   (11.04.07 15:03) [13]
>
> > Суслик ©   (11.04.07 13:24) [11]
> > ты все о своем :)
> Ну так видно же невооружённым глазом недоделанность хелперов.
>  А в статье виден результат этой недоделанности. Весь код,
>  который там нагромоздили только для того, чтобы сохранить
> текущую итерацию, мог бы с успехом сделать компилятор, и
> сделать это, я думаю, гораздо эффективнее.


Вы предлагаете ввести поля в хелперы.
Объясните нам тогда разницу по вашему между
 наследованием и HelperEx(с полями).
Покажите на примере, что можно сделать с использованием того и другого.
А чего нельзя. И что это даст.


 
Суслик ©   (2007-04-11 15:20) [15]


> Там же, где и остальные поля класса. Компилятор-то во время
> компиляции обладает информацией о наличии у класса хелперов
> и, соответственно, может учесть при выделении памяти имеющиеся
> в хелпере поля.

я думаю ты не прав :)
есть ощущение, что ты не до конца догоняешь (честное слово) хелперы.

хорошо, дабы не быть голословным

есть пакет А, в нем класс КлассА.
есть пакет Б, используется пакет А, в пакете Б есть ХелперБ.

И что? Кто должен учитывать доп. место? Пакет А ничего не знает о пакете Б. При этом пакет А может создавать объект.

Убедил?


 
oldman ©   (2007-04-11 15:20) [16]


> Суслик ©   (11.04.07 00:57)  
> Уважаемые, противники нововведний в дельфи.
> ИМХО неплохо можно использовать новые фишки в языке. Разве
> нет?


Нет.
Это будет уже другой язык.

(Кстати, а кто тебе сказал, что Дельфи - это язык программирования???)


 
oxffff ©   (2007-04-11 15:21) [17]


> (Кстати, а кто тебе сказал, что Дельфи - это язык программирования?
> ??)


А что на нем уже разговаривают?


 
Суслик ©   (2007-04-11 15:23) [18]


>  [16] oldman ©   (11.04.07 15:20)


> (Кстати, а кто тебе сказал, что Дельфи - это язык программирования???)

да не буду я спорить :)
не интересно на то как люди извращаются (с получением удовольствия, между прочим), не читай :)
мне, признаться, было весьма интересно.

-----
в одном могу согласится с общественностью - это уже тянет не другой язык с неизвестным будущем :)


 
oldman ©   (2007-04-11 15:45) [19]


> oxffff ©   (11.04.07 15:21) [17]


Вообще-то (имхо) Дельфи является средой программирования, использующую ObjectPascal, который и является языком программирования...

А то как наш бухгалтер:
"Сергей, мы купили новый компьютер, поставьте нам какую-нибудь программу. Ну, хотя-бы, Виндоуз..." :)


 
euru ©   (2007-04-11 15:47) [20]


> oxffff ©   (11.04.07 15:18) [14]
Наследование - это экстенсивный путь развития класса. Расширение функциональности класса производится за счёт создания его потомков.

Хелперы - это интенсивный путь развития класса. Расширение производится за счёт непосредственного встраивания в класс новой функциональности.

Примеры я повторю из одного из своих предыдущих сообщений.

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

С хелперами можно было бы реализовать второй вариант, а дополнительные возможности подключать к базовому классу или его потомкам по мере необходимости.

Примеры (названия классов и полей пишу по памяти, так что могу и ошибиться).
1. Поле PasswordChar в классе TEdit. Очень редко используемое поле. С хелперами можно было бы добавлять только к тем объектам TEdit, которым оно действительно нужно.

2. Свойство Dockable у класса TControl. Тоже не для всех контролов и не во всех проектах используется. Можно вынести в отдельный хелпер и подключать по мере необходимости.

3. Дублирование обычных контролов и DB-контролов. С хелперами можно было бы создать обычные контролы, а возможность работы с БД получалась бы подключением DB-хелпера.


 
homm ©   (2007-04-11 15:50) [21]

> Вообще-то (имхо) Дельфи является средой программирования,
> использующую ObjectPascal, который и является языком программирования...

Здесь не может быть «имхо», имхо. :) Начяная с версии 7 язык называется Delphi.


 
homm ©   (2007-04-11 15:51) [22]

Люди, вообще, учитесь отличать imho от afaik, а то суете не к месту и путаете вечно :(


 
oxffff ©   (2007-04-11 15:51) [23]


> oldman ©   (11.04.07 15:45) [19]
>
> > oxffff ©   (11.04.07 15:21) [17]
>
>
> Вообще-то (имхо) Дельфи является средой программирования,
>  использующую ObjectPascal, который и является языком программирования.
> ..
>
> А то как наш бухгалтер:
> "Сергей, мы купили новый компьютер, поставьте нам какую-
> нибудь программу. Ну, хотя-бы, Виндоуз..." :)


http://ru.wikipedia.org/wiki/Delphi_(%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)

Delphi — результат развития языка Турбо Паскаль, который, в свою очередь, развился из языка Паскаль. Паскаль был полностью процедурным языком, Турбо Паскаль начиная с версии 5.5 добавил в Паскаль объектно-ориентированные свойства, а Delphi — объектно-ориентированный язык программирования с возможностью доступа к метаданным классов (то есть к описанию классов и их членов) в компилируемом коде, также называемом интроспекцией. Так как все классы наследуют функции базового класса TObject, то любой указатель на объект можно преобразовать к нему, и воспользоваться методом ClassType и функцией TypeInfo, которые и обеспечат интроспекцию. Также отличительным свойством Дельфи от С++ является отсутствие возможности располагать объекты в стеке (объекты, унаследованные из Турбо Паскаля, располагаться в стеке могут) — все объекты попадают в динамически выделяемую область (кучу).

Де-факто Object Pascal, а затем и язык Delphi являются функциональными наращиваниями Turbo Pascal. Об этом говорят обозначения версий компилятора. Так, в Delphi 7 компилятор имеет номер версии 15.0 (Последняя версия Borland Pascal / Turbo Pascal обозначалась 7.0, в Delphi 1 компилятор имеет версию 8.0, в Delphi 2 — 9.0, и т. д. Номер версии 11.0 носит компилятор Pascal, входивший в состав среды C++Builder).


 
oldman ©   (2007-04-11 15:57) [24]


> homm ©   (11.04.07 15:50) [21]
> Начяная с версии 7 язык называется Delphi.


Как работал на 5, так и работаю... :)))


 
Игорь Шевченко ©   (2007-04-11 16:00) [25]

А что, неплохая иллюстрация к моим размышлениям о helper"ах - фича ради фичи


 
oxffff ©   (2007-04-11 16:01) [26]


> euru ©   (11.04.07 15:47) [20]
>
> > oxffff ©   (11.04.07 15:18) [14]
> Наследование - это экстенсивный путь развития класса. Расширение
> функциональности класса производится за счёт создания его
> потомков.
>
> Хелперы - это интенсивный путь развития класса. Расширение
> производится за счёт непосредственного встраивания в класс
> новой функциональности.


Если вы встраиваете новую функциональность, то это уже другой класс.

>С хелперами можно было бы реализовать второй вариант, а >дополнительные возможности подключать к базовому классу или его >потомкам по мере необходимости.

Это делаете наследованием или делегированием реализации.

>Примеры (названия классов и полей пишу по памяти, так что могу и >ошибиться).
>1. Поле PasswordChar в классе TEdit. Очень редко используемое поле. С >хелперами можно было бы добавлять только к тем объектам TEdit, которым >оно действительно нужно.

>2. Свойство Dockable у класса TControl. Тоже не для всех контролов и не >во всех проектах используется. Можно вынести в отдельный хелпер и >подключать по мере необходимости.

>3. Дублирование обычных контролов и DB-контролов. С хелперами можно >было бы создать обычные контролы, а возможность работы с БД получалась >бы подключением DB-хелпера.

Просто так вы не встроите поле.
Вам нужно менять функциональность класса.
Куда вы это страиваете для новой функциональности, если это не предусмотрено заранее


 
oldman ©   (2007-04-11 16:04) [27]


> Игорь Шевченко ©   (11.04.07 16:00) [25]
> А что, неплохая иллюстрация к моим размышлениям о helper"ах
> - фича ради фичи


Вообще, наводит на размышления перевод слова "helper"...
Это типа Шойгу - фича ради фичи.
:)))


 
euru ©   (2007-04-11 16:24) [28]


> Суслик ©   (11.04.07 15:20) [15]
> есть пакет А, в нем класс КлассА.есть пакет Б, используется
> пакет А, в пакете Б есть ХелперБ.И что? Кто должен учитывать
> доп. место? Пакет А ничего не знает о пакете Б. При этом
> пакет А может создавать объект.
В пакете А вызывается конструктор класса КлассА. При вызове конструктора происходит обращение к RTTI этого класса. RTTI знает о наличии хелперов у класса, а также о размере выделяемой для класса памяти с учётом всех имеющихся хелперов. На основе этой информации выделится требуемое количество памяти. Методам класса из пакета А будут доступны только поля класса (про остальные поля они просто не знают). Методам хелпера из пакета Б будут доступны задекларированные в них поля.


 
oxffff ©   (2007-04-11 16:33) [29]


> В пакете А вызывается конструктор класса КлассА. При вызове
> конструктора происходит обращение к RTTI этого класса. RTTI
> знает о наличии хелперов у класса, а также о размере выделяемой
> для класса памяти с учётом всех имеющихся хелперов.


Скажите как будет производится доступ к полям хелпера.
Offset уже могут быть разные?
через RTTI?


 
euru ©   (2007-04-11 16:47) [30]


> oxffff ©   (11.04.07 16:01) [26]
> Если вы встраиваете новую функциональность, то это уже другой класс.
Это почему? Я как объявлял TStringList, так и буду продолжать. О наличии хелпера TStringsEnumerator будет заботится компилятор.


> Это делаете наследованием или делегированием реализации.
Допустим, у нас имеется следующая иерархия классов:
type
  TA = class
    . . .
  end;

  TB = class(TA)
     . . .
  end;

  TC = class(TA)
    . . .
  end;

Через некоторое время оказалось, что у классов ТВ и ТС имеется общая функциональность, которая не была учтена в классе ТА. Исходные коды для внесения поправок недоступны. Как это будет реализовано с использованием наследования или делегирования?


> Просто так вы не встроите поле.
> Вам нужно менять функциональность класса.
Конечно. Кроме описания полей нужно ещё будет перекрыть виртуальные методы класса.


 
Игорь Шевченко ©   (2007-04-11 16:57) [31]


> RTTI знает о наличии хелперов у класса


А нафига тогда helper"ы вообще ?


 
Игорь Шевченко ©   (2007-04-11 16:58) [32]


> Через некоторое время оказалось, что у классов ТВ и ТС имеется
> общая функциональность, которая не была учтена в классе
> ТА. Исходные коды для внесения поправок недоступны.


Значит и поправки недоступны, нес па ?


 
oxffff ©   (2007-04-11 17:02) [33]


> Через некоторое время оказалось, что у классов ТВ и ТС имеется
> общая функциональность, которая не была учтена в классе
> ТА. Исходные коды для внесения поправок недоступны. Как
> это будет реализовано с использованием наследования или
> делегирования?


Кем не учтена? Вами? Автором?

> Просто так вы не встроите поле.
> Вам нужно менять функциональность класса.
Конечно. Кроме описания полей нужно ещё будет перекрыть виртуальные методы класса.

Модифицируемые методы могут быть не виртуальные(не динамические).


Самое главное, то что изменяется VTB и DMT класса.
А это уже другой класс.


Скажите как будет производится доступ к полям хелпера.
Offset уже могут быть разные?
через RTTI?


 
oxffff ©   (2007-04-11 17:04) [34]

VTB = VMT


 
euru ©   (2007-04-11 17:06) [35]


> Игорь Шевченко ©   (11.04.07 16:58) [32]
> Значит и поправки недоступны, нес па ?
При наследовании и делегировании недоступны. С хелперами это разрешимо.
type
  TAHelper = class helper for TA
    . . .
  end;

Классы и ТС автоматически получат дополнительную функциональность хелпера.


 
Игорь Шевченко ©   (2007-04-11 17:12) [36]


> Через некоторое время оказалось, что у классов ТВ и ТС имеется
> общая функциональность, которая не была учтена в классе
> ТА. Исходные коды для внесения поправок недоступны



> При наследовании и делегировании недоступны. С хелперами
> это разрешимо.
> type
>   TAHelper = class helper for TA
>     . . .
>   end;
> Классы TВ и ТС автоматически получат дополнительную функциональность
> хелпера


пример в студию не затруднит ?
исходные тексты TA, TB, TC недоступны


 
euru ©   (2007-04-11 17:16) [37]


> oxffff ©   (11.04.07 17:02) [33]
> Кем не учтена? Вами? Автором?
Не учтена тем, кто создавал эту иерархию. А последующие разработчики по различным причинам (в том числе и юридическим) не могут/не имеют права вносить коррективы.


> Модифицируемые методы могут быть не виртуальные(не динамические).
Точно такая же проблема есть и при наследовании, однако она почему-то не приводит к отказу от этой парадигмы.


> Самое главное, то что изменяется VTB и DMT класса. А это
> уже другой класс.
Для компилятора, возможно, и другой. Для разработчика останется тем же.


> Скажите как будет производится доступ к полям хелпера.
> через RTTI?
А почему бы и нет?


 
_Аноним   (2007-04-11 17:27) [38]

Зачем спорить о том, чего нет? :-)


 
oldman ©   (2007-04-11 17:36) [39]


> _Аноним   (11.04.07 17:27) [38]
> Зачем спорить о том, чего нет? :-)


А мало тут было веток про НЛО, барабашек, пиво за 2.20???


 
euru ©   (2007-04-11 17:43) [40]


> _Аноним   (11.04.07 17:27) [38]
> Зачем спорить о том, чего нет? :-)
Но это может появиться в будущем.


 
oxffff ©   (2007-04-11 17:50) [41]


> euru ©   (11.04.07 17:06) [35]
>
> > Игорь Шевченко ©   (11.04.07 16:58) [32]
> > Значит и поправки недоступны, нес па ?
> При наследовании и делегировании недоступны. С хелперами
> это разрешимо.
> type
>   TAHelper = class helper for TA
>     . . .
>   end;
> Классы TВ и ТС автоматически получат дополнительную функциональность
> хелпера.


Только эти две функциональности соседствуют независимо друг от друга.
А ваши tricks по поводу модификации VMT и DMТ это только tricks.


 
euru ©   (2007-04-11 17:51) [42]


> Игорь Шевченко ©   (11.04.07 17:12) [36]
> пример в студию не затруднит ?
Какие примеры? Имеется .dcu-файл (например, Unit1.dcu), содержащий классы ТА, ТВ и ТС, к нему прилагается справка.
В программме объявляю uses Unit1, а дальше как в [35]. После чего могу в своей программе объявить, например, переменную С: ТС. И у неё будут возможности, добавленные хелпером к классу ТА.


 
oxffff ©   (2007-04-11 17:53) [43]


> euru ©   (11.04.07 17:51) [42]
>
> > Игорь Шевченко ©   (11.04.07 17:12) [36]
> > пример в студию не затруднит ?
> Какие примеры? Имеется .dcu-файл (например, Unit1.dcu),
> содержащий классы ТА, ТВ и ТС, к нему прилагается справка.
>  
> В программме объявляю uses Unit1, а дальше как в [35]. После
> чего могу в своей программе объявить, например, переменную
> С: ТС. И у неё будут возможности, добавленные хелпером к
> классу ТА.


Вы хотите лошади пределать колеса.
Ну а если лошадь не полиморфна, что делать?


 
euru ©   (2007-04-11 17:54) [44]


> oxffff ©   (11.04.07 17:50) [41]
> Только эти две функциональности соседствуют независимо друг
> от друга.
Не понял этой фразы. Можно поподробнее?


> А ваши tricks по поводу модификации VMT и DMТ это только
> tricks.
Tricks они до тех пор, пока не будут поддерживаться компилятором.


 
oxffff ©   (2007-04-11 17:54) [45]


> euru ©   (11.04.07 17:51) [42]
>
> > Игорь Шевченко ©   (11.04.07 17:12) [36]
> > пример в студию не затруднит ?
> Какие примеры? Имеется .dcu-файл (например, Unit1.dcu),
> содержащий классы ТА, ТВ и ТС, к нему прилагается справка.
>  
> В программме объявляю uses Unit1, а дальше как в [35]. После
> чего могу в своей программе объявить, например, переменную
> С: ТС. И у неё будут возможности, добавленные хелпером к
> классу ТА.


Наследуйте от класса.


 
euru ©   (2007-04-11 17:55) [46]


> oxffff ©   (11.04.07 17:53) [43]

> Вы хотите лошади пределать колеса.Ну а если лошадь не полиморфна,
>  что делать?
А наследование как с такой задачей справится?


 
euru ©   (2007-04-11 17:57) [47]


> oxffff ©   (11.04.07 17:54) [45]

> Наследуйте от класса.
Тогда мне нужно будет создать наследника для каждого потомка класса ТА


 
oldman ©   (2007-04-11 17:58) [48]

Почему нет надписи:

Перемещено в конференцию "Бред"

???


 
oxffff ©   (2007-04-11 17:59) [49]


> euru ©   (11.04.07 17:54) [44]
>
> > oxffff ©   (11.04.07 17:50) [41]
> > Только эти две функциональности соседствуют независимо
> друг
> > от друга.
> Не понял этой фразы. Можно поподробнее?


Одна функциональность расширяет и (не)использует другую, но не переопределяет ее.
Если она переопределяет ее это уже наследование.


 
oxffff ©   (2007-04-11 18:01) [50]


> А наследование как с такой задачей справится?


Никак. Но вы можете определить новый класс Лошадь на колесах.
И два агрегата, которым делегируется реализация этого класса.


 
Игорь Шевченко ©   (2007-04-11 18:13) [51]


> Какие примеры? Имеется .dcu-файл (например, Unit1.dcu),
> содержащий классы ТА, ТВ и ТС, к нему прилагается справка.
>  
> В программме объявляю uses Unit1, а дальше как в [35]. После
> чего могу в своей программе объявить, например, переменную
> С: ТС. И у неё будут возможности, добавленные хелпером к
> классу ТА.


Я конечно все понимаю, но не проще функцию объявить, которая будет делать ту недостающую функциональность, чем напрягать программиста, увидевшего вызовы методов, напрочь отсутствующих в справке ?

Или опять фича ради фичи ?


 
_Аноним   (2007-04-11 18:19) [52]


> Я конечно все понимаю, но не проще функцию объявить, которая
> будет делать ту недостающую функциональность, чем напрягать
> программиста, увидевшего вызовы методов, напрочь отсутствующих
> в справке ?


Это решается путем Ctrl+Click


 
Игорь Шевченко ©   (2007-04-11 18:41) [53]


> Это решается путем Ctrl+Click


Это если у тебя времени много


 
_Аноним   (2007-04-11 19:21) [54]


> Игорь Шевченко ©

А функция (та, которая вместо хелпера) разве присутствует в справке?

> Это если у тебя времени много

Ctrl+Click быстрее работает, чем F1


 
euru ©   (2007-04-12 02:50) [55]


> oxffff ©   (11.04.07 17:59) [49]
> Одна функциональность расширяет и (не)использует другую,
>  но не переопределяет ее.Если она переопределяет ее это
> уже наследование.
Странно. Насколько я знаю, в результате наследования появляется новый класс. Применение хелперов новые классы не порождает. С чего же тогда здесь должно быт наследование?


> Игорь Шевченко ©   (11.04.07 18:13) [51]
> Я конечно все понимаю, но не проще функцию объявить,
Ну да. Десяток функций, заменяющих хелпер. Плюс ещё где-то нужно хранить структуру с дополнительными полями несостоявшегося хелпера. Плюс ещё помнить, что эта структура принадлежит конкретному классу. Плюс ещё продублировать все функции для потомков класса либо в оригинальных функциях case для каждого потомка класса прописывать и не забывать обновлять эту функцию при очередном наследовании.


 
oxffff ©   (2007-04-12 09:38) [56]


> euru ©   (12.04.07 02:50) [55]
>
> > oxffff ©   (11.04.07 17:59) [49]
> > Одна функциональность расширяет и (не)использует другую,
>
> >  но не переопределяет ее.Если она переопределяет ее это
>
> > уже наследование.
> Странно. Насколько я знаю, в результате наследования появляется
> новый класс. Применение хелперов новые классы не порождает.
>  С чего же тогда здесь должно быт наследование?


(Хелпер с полями + перекрытие методов класса)
грубо = наследование.


 
Alkid ©   (2007-04-12 10:06) [57]

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

Цитата:
"A class helper simply introduces a wider scope for the compiler to use when resolving identifiers"


 
_Аноним   (2007-04-12 10:29) [58]


> Alkid ©


А мы тут обсуждаем гипотетическую возможность того, что в след. версии уже можно будет и поля определять.

По сабжу.
Игорь, ты ведь их не используешь, хелперы, правильно?
Не используешь.
И ты теоретически предполагаешь ,что при их использовании возможны засады - программисты запутаются и начнется бардак.
А мы используем, на практике. Ну нет от них никакой путаницы, нету, как бы не казалось, что она может бьть.
Наоборот, структура модулей заметно упорядочилась.
Это практика, она главнее :-)


 
Alkid ©   (2007-04-12 10:35) [59]


> А мы тут обсуждаем гипотетическую возможность того, что
> в след. версии уже можно будет и поля определять.

Вряд ли такое случится.


 
oxffff ©   (2007-04-12 11:02) [60]


> Alkid ©   (12.04.07 10:35) [59]
>
> > А мы тут обсуждаем гипотетическую возможность того, что
>
> > в след. версии уже можно будет и поля определять.
>
> Вряд ли такое случится.


Для такого события должны быть причины.
На сегодняшний момент таких причин нет.

Загляну в будущее и скажу больше "Их и там не будет"


 
oxffff ©   (2007-04-12 11:12) [61]


> _Аноним   (12.04.07 10:29) [58]
>
> > Alkid ©
>
>
> А мы тут обсуждаем гипотетическую возможность того, что
> в след. версии уже можно будет и поля определять.


Если эту версию выпустит euru ©.
:)

Если серьезно, то

Class helpers
сlass helper is a
construct that extends a class with all fields from the helper class. It allows
you to extend existing class without actually modifying it or inheriting from it.

The reason why this feature was included in Delphi was to make VCL portable
to .NET.


 
Игорь Шевченко ©   (2007-04-12 11:37) [62]

_Аноним   (12.04.07 10:29) [58]


> Игорь, ты ведь их не используешь, хелперы, правильно?
> Не используешь.
> И ты теоретически предполагаешь ,что при их использовании
> возможны засады - программисты запутаются и начнется бардак.
>


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


> А мы используем, на практике. Ну нет от них никакой путаницы,
>  нету, как бы не казалось, что она может бьть.
> Наоборот, структура модулей заметно упорядочилась.


Вы тоже VCL с .Net скрещиваете ? :)

Ты б хоть пример тогда реальный привел, раз вы их используете вовсю.


 
euru ©   (2007-04-12 12:17) [63]


> oxffff ©   (12.04.07 09:38) [56]
> (Хелпер с полями + перекрытие методов класса) грубо = наследование.

Возьму пример с лошадью, только с полиморфной.
Допустим, имеется следующая иерархия.

type
  TAnimal = class
  public
    procedure Draw(); virtual;
  end;

  THorse = class(TAnimal)
  public
    procedure Draw(); override;
  end;

  TDog = class(TAnimal)
  public
    procedure Draw(); override;
  end;

var
  H: THorse;
  D: TDog;

begin
  H := THorse.Create();
  D := TDog.Create();
  H.Draw();
  D.Draw();
end;


Необходимо добавить возможность рисования колёс для потомков класса TAnimal.

Наследование.

type
  TWheelHorse = class(THorse)
  private
    FWheelParams: TWheelParams;
  public
    procedure Draw(); override;
  end;

  TWheelDog = class(TDog)
  private
    FWheelParams: TWheelParams;
  public
    procedure Draw(); override;
  end;

  // Функция, умеющая рисовать колёса потомкам класса TAnimal
  procedure DrawWheels(Animal: TAnimal; Params: TWheelParams);

procedure TWheelHorse.Draw();
begin
  inherited Draw();
  DrawWheels(Self, FWheelParams);
end;

procedure TWheelDog.Draw();
begin
  inherited Draw();
  DrawWheels(Self, FWheelParams);
end;

Ещё нужно не забыть переписать создание объектов, чтобы учесть изменения.
begin
  H := TWheelHorse.Create();
  D := TWheelDog.Create();
  H.Draw();
  D.Draw();
end;


Хелперы

type
  TAnimalHelper = class helper for TAnimal
  private
    FWheelParams: TWheelParams;
    private DrawWheels();
  public
    procedure Draw(); override;
  end;

procedure TAnimalHelper.Draw();
begin
  inherited;
  DrawWheels();
end;

При создании объектов классов THorse и TDog автоматически учтётся расширение их предка хелпером.


 
_Аноним   (2007-04-12 12:24) [64]


> Игорь Шевченко ©  


> Вы тоже VCL с .Net скрещиваете ? :)
>
> Ты б хоть пример тогда реальный привел, раз вы их используете
> вовсю.


нет, не скрещиваем, у нас чистый win32

Используются они у нас в двух случаях:
1.
Некий набор утилит общего назначения - дополнение к классам VCL
Структура модулей с хелперами повторяет структуру модулей VCL
то есть у нас например есть модули типа
MyLib.Helpers.Classes
MyLib.Helpers.StdCtrls
MyLib.Helpers.ComCtrls
MyLib.Helpers.Forms

Пример хелпера общего назначения:

 TStringsHelper = class Helper for TStrings
 public
   function AddObjectFmt(const s: string; const Args: array of const; Obj: TObject): Integer;
   function AddFmt(const s: string; const Args: array of const): Integer;

2. В конкретный местах, где требуется расширение фунцкиональности базовой иерархии начиная с предка - конктерно для использовании в конкретном модуле проекта (не библиотеке)
(сорри за тавтологию)

В базовых иерархиях мы хелперы не используем.


 
Игорь Шевченко ©   (2007-04-12 12:26) [65]


>  TStringsHelper = class Helper for TStrings
>  public
>    function AddObjectFmt(const s: string; const Args: array
> of const; Obj: TObject): Integer;
>    function AddFmt(const s: string; const Args: array of
> const): Integer;


Ну да, а функцию завести вам точно Коран не велит. 18-ая сура.

Так хорошо написать MyFooList.AddFmt вместо AddFmt(MyFooList)


 
_Аноним   (2007-04-12 12:34) [66]


> Игорь Шевченко ©  


Да понятно, что можно и функцией.
Но так красивее :-)


> Коран не велит. 18-ая сура.


В народе ходил слух, что ты являешься дервишом суфийского ордена Кадерия.
Неужели правда? :-)


 
Игорь Шевченко ©   (2007-04-12 12:40) [67]

_Аноним   (12.04.07 12:34) [66]


> Но так красивее :-)


Красота - убойная сила. Но мне предпочительнее понятность, потому как видя вызов функции я без Ctrl+Mouse пойму, что это изобретение программиста, а не фирмы Borland к примеру, или фирмы-поставщика стороннего класса.


> В народе ходил слух, что ты являешься дервишом суфийского
> ордена Кадерия.
> Неужели правда? :-)


Пляшущим :)


 
oxffff ©   (2007-04-12 12:47) [68]


> Хелперы
>
> type
>   TAnimalHelper = class helper for TAnimal
>   private
>     FWheelParams: TWheelParams;
>     private DrawWheels();
>   public
>     procedure Draw(); override;
>   end;
>
> procedure TAnimalHelper.Draw();
> begin
>   inherited;
>   DrawWheels();
> end;
> При создании объектов классов THorse и TDog автоматически
> учтётся расширение их предка хелпером.


Во первых у вас все животные будут с колесами.

:)

А во вторых

procedure TAnimalHelper.Draw(); override;

заменит entry VMT в классе.

Во вашим словам helpers могут расширять TAnimal.
Их может быть много.
Скажите если я позже захочу еще и крылья рисовать, то есть и колеса и крылья, то как вы это собрались override?


 
euru ©   (2007-04-12 14:03) [69]


> Игорь Шевченко ©   (12.04.07 12:40) [67]

>  Но мне предпочительнее понятность, потому как видя вызов
> функции я без Ctrl+Mouse пойму, что это изобретение программиста,
>  а не фирмы Borland к примеру, или фирмы-поставщика стороннего
> класса.
Допустим, встречается внутри метода класса вызов
AddFmt(MyFooList)
Как определить, что это:
1. вызов глобальной функции;
2. вызов метода из того же класса или его предка;
3. вызов метода из делегированного интерфейса.


 
clickmaker ©   (2007-04-12 14:05) [70]


> [67] Игорь Шевченко ©   (12.04.07 12:40)
> > В народе ходил слух, что ты являешься дервишом суфийского
>
> > ордена Кадерия.
> > Неужели правда? :-)
>
>
> Пляшущим :)

с бубном? :)


 
euru ©   (2007-04-12 14:22) [71]


> oxffff ©   (12.04.07 12:47) [68]
> Во первых у вас все животные будут с колесами.
Не важно. Целью было показать разницу между наследованием и хелперами.


> заменит entry VMT в классе.
А что в этом криминального?


> Скажите если я позже захочу еще и крылья рисовать, то есть
> и колеса и крылья, то как вы это собрались override?
Например, так
type
  TWingsAnimalHelper = class helper(TAnimalHelper) for TAnimal
  private
    FWingsParams: TWingsParams;
  public
    procedure Draw(); override;
  end;


 
Игорь Шевченко ©   (2007-04-12 14:29) [72]

euru ©   (12.04.07 14:03) [69]


> Допустим, встречается внутри метода класса вызов



> Как определить, что это:


А сейчас ты как определяешь ?


 
oxffff ©   (2007-04-12 14:42) [73]


> euru ©   (12.04.07 14:22) [71]
>
> > oxffff ©   (12.04.07 12:47) [68]
> > Во первых у вас все животные будут с колесами.
> Не важно. Целью было показать разницу между наследованием
> и хелперами.
>
>
> > заменит entry VMT в классе.
> А что в этом криминального?
>
>
> > Скажите если я позже захочу еще и крылья рисовать, то
> есть
> > и колеса и крылья, то как вы это собрались override?
> Например, так
> type
>   TWingsAnimalHelper = class helper(TAnimalHelper) for TAnimal
>   private
>     FWingsParams: TWingsParams;
>   public
>     procedure Draw(); override;
>   end;


Чем это отличается наследования?


 
oxffff ©   (2007-04-12 14:45) [74]

to euru

> > > Во первых у вас все животные будут с колесами.
> > Не важно. Целью было показать разницу между наследованием
>
> > и хелперами.
> >


По моему в вашем понимании это одно и тоже (в смысле результат)


 
euru ©   (2007-04-12 14:46) [75]


> Игорь Шевченко ©   (12.04.07 14:29) [72]
> А сейчас ты как определяешь ?
Я уже года два никак это не определяю :)
А раньше Ctrl+LeftClick. Но, насколько я понял, у тебя есть методика, как обойтись такого способа. Вот мне и интересно стало.


 
euru ©   (2007-04-12 15:08) [76]


> euru ©   (12.04.07 14:46) [75]
как обойтись такого способа = как обойтись без такого способа


 
Игорь Шевченко ©   (2007-04-12 15:39) [77]

euru ©   (12.04.07 14:46) [75]

Есть методика - глаза.exe называется. До сих пор оправдывала. Для стандратных (читай - VCL, RTL) классов список их методов в голове находится, поэтому определить, что AddFmt с параметром Tstrings и дополнительными явно является функцией или методом класса, отличного от TStrings, труда не составляет. А вот увидев у экземпляра класса TStrings вызов метода AddFmt скорость распознавания текста сильно замедляется, до ступора.


 
Alkid ©   (2007-04-12 16:33) [78]


> Например, так
> type
>   TWingsAnimalHelper = class helper(TAnimalHelper) for TAnimal
>   private
>     FWingsParams: TWingsParams;
>   public
>     procedure Draw(); override;
>   end;

Замечательно. Есть у меня класс TAnimal и наследники. Есть хелпер TWheeledAnimal и есть хелпер TWingedAnimal. Я создаю экземпляр THorse и вызываю у него Draw. У меня какой конь нарисуется - с колёсами или с крыльями?

А вообще то, что предлагается - это бред с точки зрения классического ООП, ибо поведение класса меняется извне этого класса, что напрямую противоречит парадигме ООП.


 
oxffff ©   (2007-04-12 17:16) [79]


> Замечательно. Есть у меня класс TAnimal и наследники. Есть
> хелпер TWheeledAnimal и есть хелпер TWingedAnimal. Я создаю
> экземпляр THorse и вызываю у него Draw. У меня какой конь
> нарисуется - с колёсами или с крыльями?


Я его тоже к этому пытался подвести.
Но конь будет с тем, что объявлено последним.
Скорее с хвостом. :)

>А вообще то, что предлагается - это бред с точки зрения классического >ООП, ибо поведение класса меняется извне этого класса, что напрямую >противоречит парадигме ООП.

Скорее дублирует уже существующую функциональность.


 
Alkid ©   (2007-04-12 17:21) [80]


> Я его тоже к этому пытался подвести.
> Но конь будет с тем, что объявлено последним.
> Скорее с хвостом. :)

Да нет, это будет крылато-колесатый конь :)


> Скорее дублирует уже существующую функциональность.

Не дулирует.  Это прямое нарушение.
Предположим: есть базовый класс А со стандартизованным описанием и интерфейсов. От этого класса пронаследовались другие классы. Теперь появляется третья сторона, которая получает возможность вмешатьяс в интерфейс и поведение класса А, каскадно изменив тем самым поведением всех остальных классов. Это прямое нарушение принципов инкапсуляции и прекрасная возможность создания себе проблем :-)

Собственно говоря, если возникает необходимость таким экзотическим образом менять способ отрисовки целой иерархии классов, то значит иерархия была спроектирована неправильно, способ отрисовки должен быть выделен в стратегию и т.п.


 
euru ©   (2007-04-12 18:05) [81]


> Alkid ©   (12.04.07 16:33) [78] и т.д.

> Замечательно. Есть у меня класс TAnimal и наследники. Есть
> хелпер TWheeledAnimal и есть хелпер TWingedAnimal. Я создаю
> экземпляр THorse и вызываю у него Draw. У меня какой конь
> нарисуется - с колёсами или с крыльями?
Это для меня не неожиданный поворот событий. Я о нём знаю. Более того, если в [63] внимательно посмотреть последовательность вызовов, то обнаружится следующее:

- при наследовании TWheelHorse.Draw() развернётся в
    TAnimal.Draw();
    THorse.Draw();
    DrawWheels(Self, FWheelParams);


- при использовании хелперов THorse.Draw() с хелпером развернётся в
    TAnimal.Draw();
    TAnimalHelper.DrawWheels();
    THorse.Draw();


Т.е. возникает коллизия в последовательности вызовов. Просто до сих пор шло обсуждение принципиальной возможности реализации хелперов с полями и их отличия от наследования.

А по поводу очерёдности вызова. Так как хелпер встраивается в уже готовую конструкцию, то в языке, естественно, должна быть возможность чётко определять последовательность применения хелперов и их методов.


> А вообще то, что предлагается - это бред с точки зрения
> классического ООП, ибо поведение класса меняется извне этого
> класса, что напрямую противоречит парадигме ООП.
Парадигма ООП - это не истина в последней инстанции. Есть ещё парадигма аспектно-ориентированного программирования (АОП). Она тоже с точки зрения ООП является бредом.
Однако, можно познакомиться с мнением Гради Буча http://www.sdmagazine.com/documents/s=843/sdm0107i/0107i.htm

И вообще почитать про АОП http://www.javable.com/columns/aop/


 
GrayFace ©   (2007-04-12 20:30) [82]

euru ©   (11.04.07 15:03) [13]
А если учесть и другие несуразности, возникшие с вводом в язык новых понятий (о них я писал в [41] в http://delphimaster.net/view/15-1176238641/), то у меня возникают вопросы о квалифицированности разработчиков языка либо об их отношению к языку.

Честно говоря, тебе лучше задать вопрос о квалифицированности самому себе.

homm ©   (11.04.07 15:51) [22]
Люди, вообще, учитесь отличать imho от afaik, а то суете не к месту и путаете вечно :(

Имхо, afaik расшифровывается как AsFarAsIKnow, а imho - InMyHumbleOpinion, по этому, afaik, в этом предложении я написал что-то не так.

euru ©   (11.04.07 16:24) [28]
В такой реализации не добавляется ничего нового, применение таких хелперов точно такое же, как у наследования, только добавляется масса ненужных проблем.

euru ©   (11.04.07 17:54) [44]
Tricks они до тех пор, пока не будут поддерживаться компилятором.

Компилятор наш, сущий на небесах, да святится имя твое... Комилятор не всемогущь.

euru ©   (12.04.07 12:17) [63]
С множественным наследованием:
type
 TAnimalDrawer = class(TAnimal)
 private
   FWheelParams: TWheelParams;
   private DrawWheels();
 public
   procedure Draw(); override;
 end;

 TWheelHorse = class(THorse, TAnimalDrawer)
 end;

 TWheelDog = class(TDog, TAnimalDrawer)
 end;

procedure TAnimalDrawer.Draw();
begin
 inherited;
 DrawWheels();
end;


euru ©   (12.04.07 18:05) [81]
Просто до сих пор шло обсуждение принципиальной возможности реализации хелперов с полями и их отличия от наследования.

Да, все говорили о их реализации, а ты говорил исключительно об их применении.
Скажи наконец, что должен делать компилятор, чтобы осуществить твой коварный замысел?


 
GrayFace ©   (2007-04-12 20:33) [83]

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


 
_Аноним   (2007-04-12 22:59) [84]

Кстати вопрос сторонникам теории "добавить поддержку полей в хелперы"
а что делать компилеру ,если они  (класс и хелпер к нему) вдруг попадут в разные ран-тайм пакеты?


 
Суслик ©   (2007-04-13 00:20) [85]


> _Аноним   (12.04.07 22:59) [84]

+10


 
jack128 ©   (2007-04-13 02:41) [86]

_Аноним   (12.04.07 22:59) [84]
Это вопрос уже ставился перед сторонниками недели три назад. Ответа не было тогда, не думаю, что он появится сейчас...


 
Суслик ©   (2007-04-13 09:15) [87]

Появилась у меня идея. Наверное не совсем хорошо, когда какой хелпер применять компилятор решает только на основе скопа - т.е. берется ближайший по области видимости хелпер.

Я считаю, что было бы хдорово, если бы можно было указывать хелпер явно.
например, что-то типа такого


uses
  MyClassHelper, MyClassHelper2;
...
var
  C: TMyClass apply TMyClassHelper;
  C1: TMyClass apply TMyClassHelper2;
  С2: TMyClass


В первом случае примняется хелпер TMyClassHelper, во втором TMyClassHelper2, в третьем - снова TMyClassHelper2, как ближайший по скопу.

Как считаете?


 
oxffff ©   (2007-04-13 12:07) [88]


> Alkid ©   (12.04.07 17:21) [80]
>
> > Я его тоже к этому пытался подвести.
> > Но конь будет с тем, что объявлено последним.
> > Скорее с хвостом. :)
>
> Да нет, это будет крылато-колесатый конь :)
>
>
> > Скорее дублирует уже существующую функциональность.
>
> Не дулирует.  Это прямое нарушение.
> Предположим: есть базовый класс А со стандартизованным описанием
> и интерфейсов. От этого класса пронаследовались другие классы.
>  Теперь появляется третья сторона, которая получает возможность
> вмешатьяс в интерфейс и поведение класса А, каскадно изменив
> тем самым поведением всех остальных классов. Это прямое
> нарушение принципов инкапсуляции и прекрасная возможность
> создания себе проблем :-)


C инкапсуляцией это никак не связано.
Это возможность модификации базового класса.

to euro

Как отличить один класс(без apply helper) и другой класс(с apply helper).

Для каждого из них будет создана разная VMT(СlassType),
если вы допускаете возможность override.


Это будет указывать на разные типы.


 
oxffff ©   (2007-04-13 12:07) [89]


> C инкапсуляцией это никак не связано.
> Это возможность модификации базового класса.


Но только VMT и DMT. И то если это предусмотрено.


 
oxffff ©   (2007-04-13 12:13) [90]

to euro

>Аспектно-ориентированное программирование — новая парадигма >программирования, которая позволяет реализовывать отдельные концепции >в слабосвязанном виде, и, комбинируя такие реализации, сформировать >конечную систему

А чем вас COM не устраивает.


 
euru ©   (2007-04-13 17:17) [91]


> GrayFace ©   (12.04.07 20:30) [82]

> С множественным наследованием:
Множественное наследование не расширило возможности класса, а создало два новых класса с расширенными возможностями. Всё равно придётся искать все места, где создаются объекты THorse и TDog и заменять их на TWheelHorse и TWheelDog.


> GrayFace ©   (12.04.07 20:33) [83]

> Создание новых машин - это экстенсивный путь развития автомабилестроения.
>  Куда лучше было бы идти по интенсивному пути, добавляя
> новую функциональность в уже существующие машины.
Насколько я знаю, именно по такому пути автомобилестроение и развивается. Изобретение нового элемента автомобиля (ABS, АКПП и т.д.) не приводит к созданию нового типа автомобиля. Эти элементы добавляют в уже существующие типы автомобилей.
Если бы автомобилестроение придерживалось классического ООП, да ещё и с единичным наследованием, то на внесение каждого изменения пришлось бы изобретать новое название модели.


 
oxffff ©   (2007-04-13 17:29) [92]

to  euru ©  
Пожалуйста ваш ответ на oxffff ©   (13.04.07 12:07) [88]?


 
euru ©   (2007-04-13 18:04) [93]


> _Аноним   (12.04.07 22:59) [84]

> а что делать компилеру ,если они  (класс и хелпер к нему)
> вдруг попадут в разные ран-тайм пакеты?
А чем не устраивает ответ [28]?

Я набросал небольшой пример имитации. Но, к сожалению, Delphi у меня не установлен. Я постарался, насколько смог, не допустить синтаксических ошибок и промоделировать корректность работы, но 100% гарантии дать не могу.

За основу я взял свой предыдущий пример с лошадью и собакой. Внёс в него некоторые изменения, которые, в принципе, мог бы сделать и компилятор. Для имитации хелперов я использовал интерфейсы.

Модуль Animals.pas содержит реализацию трёх классов: TAnimal, THorse и TDog. Интерфейс IAnimalHelper имитирует хелпер. Процедура RegisterHelper имитирует объявление class helper.

unit Animals;

interface

type
 //Порядок вызова хелперов
 TCallOrder = (
     coBefore,  // вызов перед вызовом хелпера предка
     coInstead,  // вызов вместо текущего хелпера
     coAfter  // вызов после вызова хелпера предка
 );

 IAnimalHelper = interface
   procedure Draw();
 end;

 TAnimal = class
 public
   // Процедура регистрации хелпера
   //    Привязывает хелпер к классу, вызывающему процедуру
   class procedure RegisterHelper(aHelper: IAnimalHelper;
       aCallOrder: TCallOrder = coAfter);

   procedure Draw();
 end;

 THorse = class(TAnimal)
 end;

 TDog = class(TAnimal)
 end;

implementation

type
 TAnimalClass = class of TAnimal;

 THelperHandle = class
 public
   Owner: TAnimalClass;
   Helper: IAnimalHelper;
   Order: TCallOrder;
   Parent: PHelperHandle;
   Before: PHelperHandle;
   After: PHelperHandle;
   constructor Create(aOwner: TAnimalClass; aHelper: IAnimalHelper);
   destructor Destroy(); override;
 end;

constructor THelperHandle.Create(aOwner: TAnimalClass; aHelper: IAnimalHelper);
begin
 Owner := aOwner;
 Helper := aHelper;
 Order := coInstead;
 Parent := nil
 Before := nil;
 After := nil;
end;

destructor THelperHandle.Destroy();
begin
 if Before <> nil then FreeAndNil(Before);
 if After <> nil then FreeAndNil(After);
 Helper := nil;
 inherited;
end;

type
 TAnimalHelpers = class
 private
   FHelpers: TStringList;
 public
   constructor Create();
   destructor Destroy(); override;
   procedure AddHelper(aParent: THelperHandle; aClass: TAnimalClass;
       aHelper: IAnimalHelper; aCallOrder: TCallOrder);
   function GetHelperHandle(aClass: TAnimalClass): THelperHandle;
 end;

constructor TAnimalHelpers.Create();
begin
 FHelpers := TStringList.Create();
end;

destructor TAnimalHelpers.Destroy();
var
 Handle: TObject;
 i: Integer;
begin
 for i := 0 to FHelpers.Count - 1 do begin
   Handle := FHelpers.Objects[i];
   if Handle <> nil then Handle.Free();
 end;
 FHelpers.Free();
 inherited;
end;

procedure TAnimalHelpers.AddHelper(aParent: THelperHandle;
   aClass: TAnimalClass; aHelper: IAnimalHelper; aCallOrder: TCallOrder);
begin
 Handle := THelperHandle.Create(aClass, aHelper);
 if (aParent <> nil) and (aParent.Owner = aClass) then begin
   case aCallOrder of
     coBefore: begin
         Handle.Before := aParent.Before;
         aParent.Before := Handle;
       end;
     coInstead: begin
         aParent.Helper := aHelper;
         Handle.Free();
       end;
     coAfter: begin
         Handle.After := aParent.After;
         aParent.After := Handle;
       end;
   end;
 end
 else begin
   FHelpers.AddObject(aClass.ClassName(), Handle);
   Handle.Parent := aParent;
   Handle.Order := aCallOrder;
   for i := 0 to FHelpers.Count - 1 do begin
     Child := THelperHandle(FHelpers.Objects[i]);
     if (Child.Parent = aParent) and
         Child.Owner.InheritsFrom(aClass) then begin
       Child.Parent := Handle;
     end;
   end;
 end;
end;

function TAnimalHelpers.GetHelperHandle(aClass: TAnimalClass): THelperHandle;
var
 Current: TAnimalClass;
begin
 Result := nil;
 Current := aClass;
 while True do begin
   if FHelpers.Find(Current.ClassName(), Index) then begin
     Result := THelperHandle(FHelpers.Objects[Index]);
     exit;
   end;
   if Current = TAnimal then exit;
   Current := Current.ClassParent();
 end;
end;

var
 AnimalHelpers: TAnimalHelpers;

class procedure TAnimal.RegisterHelper(aHelper: IAnimalHelper;
   aCallOrder: TCallOrder = coAfter);
var
 Handle: THelperHandle;
begin
 Handle := AnimalHelpers.GetHelperHandle(ClassType());
 AnimalHelpers.AddHelper(Handle, ClassType(), aHelper, aCallOrder);
end;

procedure TAnimal.Draw();

 procedure HelperDraw(aHandle: THelperHandle);
 begin
   if aHandle = nil then exit;

   with aHandle do begin
     case Order of
       coBefore: begin
           HelperDraw(Before);
           Helper.Draw();
           HelperDraw(After);
           HelperDraw(Parent);
         end;
       coInstead: begin
           Helper.Draw();
           HelperDraw(Before);
           HelperDraw(After);
         end;
       coAfter: begin
           HelperDraw(Parent);
           HelperDraw(Before);
           Helper.Draw();
           HelperDraw(After);
         end;
     end;
   end;
 end;

var
 Handle: PHelperHandle;
begin
 Handle := AnimalHelpers.GetHelperHandle(ClassType);
 HelperDraw(Handle);
end;

type
 TAnimalHelper = class(TInterfacedObject, IAnimalHelper)
 private
   procedure Draw();
 end;

procedure TAnimalHelper.Draw();
begin
 writeln("Я животное");
end;

type
 THorseHelper = class(TInterfacedObject, IAnimalHelper)
 private
   procedure Draw();
 end;

procedure THorseHelper.Draw();
begin
 writeln("Меня зовут Лошадь");
end;

type
 TDogHelper = class(TInterfacedObject, IAnimalHelper)
 private
   procedure Draw();
 end;

procedure TDogHelper.Draw();
begin
 writeln("Меня зовут Собака");
end;

initialization
 AnimalHelpers := TAnimalHelpers.Create();

 TAnimal.RegisterHelper(TAnimalHelper.Create());
 THorse.RegisterHelper(THorseHelper.Create());
 TDog.RegisterHelper(TDogHelper.Create());
finalization
 AnimalHelpers.Free();
end.


 
euru ©   (2007-04-13 18:05) [94]

В программе StrangeAnimals.dpr имитируются два хелпера:
- TWheeledAnimalHelper: его действие повлияет на класс TAnimal и его потомков;
- TWingedHorseHelper: его действие повлияет на класс THorse и его потомков.

При этом добавление хелперов не привело к определению новых специализированных классов, хотя поведение классов после применения хелперов изменилось.

Также можно видеть, что для изменения поведения классов из модуля Animals нет необходимости иметь в наличии исходные тексты этого модуля. Фактически, этот модуль может находится в отдельном пакете, однако это не мешает изменять его поведение (а не добавлять новое, как это делается с помощью class helper) из другого.

program StrangeAnimals;

uses
 Animals;

type
 TWheeledAnimalHelper = class(TInterfacedObject, IAnimalHelper)
 private
   procedure Draw();
 end;

 TWingedHorseHelper = class(TInterfacedObject, IAnimalHelper)
 private
   procedure Draw();
 end;

procedure TWheeledAnimalHelper.Draw();
begin
 writeln("Вместо ног у меня колёса");
end;

procedure TWingedHorseHelper.Draw();
begin
 writeln("А ещё у меня есть крылья");
end;

var
 H: THorse;
 D: TDog;

begin
 H := THorse.Create();
 D := TDog.Create();

 H.Draw();
 D.Draw();

 TAnimal.RegisterHelper(TWheeledAnimalHelper.Create());

 H.Draw();
 D.Draw();

 THorse.RegisterHelper(TWingedHorseHelper.Create(), coBefore);

 H.Draw();
 D.Draw();

 H.Free();
 D.Free();
end.


 
euru ©   (2007-04-13 18:06) [95]


> oxffff ©   (13.04.07 17:29) [92]
Отвечу.


 
_Аноним   (2007-04-13 18:24) [96]


> euru ©


>  а что делать компилеру ,если они  (класс и хелпер к нему)
>
> > вдруг попадут в разные ран-тайм пакеты?
> А чем не устраивает ответ [28]?


28:
>>RTTI знает о наличии хелперов у класса

Откуда?


 
GrayFace ©   (2007-04-14 19:22) [97]

euru ©   (13.04.07 17:17) [91]
Множественное наследование не расширило возможности класса, а создало два новых класса с расширенными возможностями. Всё равно придётся искать все места, где создаются объекты THorse и TDog и заменять их на TWheelHorse и TWheelDog.

Ну чтоб не заменять можно написать THorse = TWheelHorse, TDog = TWheelDog.

euru ©   (13.04.07 18:04) [93]
Я набросал небольшой пример имитации.

Небольшой)) Верю, что после правок ошибок (если есть) работать будет, но какой ценой... (действительно, если не экономить на скорости, схема получается проще, чем та, о которой думал я)


 
euru ©   (2007-04-16 02:55) [98]


> Суслик ©   (13.04.07 09:15) [87]
Нормальная идея. Только, может, имеет смысл рассматривать такой код не только как указание, какой из хелперов выбирать, но и как способ назначения хелпера непосредственно экземпляру класса.


> oxffff ©   (13.04.07 12:07) [88]

> Как отличить один класс(без apply helper) и другой класс(с
> apply helper).
Идея-то как раз и заключается в том, что для разработчика название класса и его тип после применения хелпера не изменялись. А если вдруг понадобится информация о наличии в классе хелпера, то можно, например, задействовать оператор is.


> Для каждого из них будет создана разная VMT(СlassType),если
> вы допускаете возможность override.
Наличие VMT в откомпилированной программе -- это внутреннее представление (способ реализации) полиморфизма классов. Как именно будет реализован этот механизм при наличии хелперов, не должно волновать разработчиков. То, что в данной версии Delphi тип класса и VMT эквивалентны, является просто следствием реализации и не факт, что в последующих версиях это условие будет соблюдаться. Вполне возможно, что будет использоваться какая-нибудь XMT (eXtended Method Table), в составе которой будет информация и о виртуальных методах.


> oxffff ©   (13.04.07 12:13) [90]

> А чем вас COM не устраивает.
Аспекты и СОМ - это несколько разные вещи.
Это всё равно, что сравнить в языке Java атрибут метода synchronized и функции EnterCriticalSection, LeaveCriticalSection.


> GrayFace ©   (14.04.07 19:22) [97]

> Ну чтоб не заменять можно написать THorse = TWheelHorse,
>  TDog = TWheelDog.
Т.е. сначала создать два новых класса, а потом определить ещё два класса, имена которых совпадают с именами нужных нам классов, но их типы являются различными? А чем это удобнее хелперов?


>  Верю, что после правок ошибок (если есть) работать будет,
>  но какой ценой...
Для проверки работы специально скачал триальную версию Delphi. Обнаружены следующие недочёты в модуле Animals.pas:
1. В разделе implementation добавить модули SysUtils и Classes.
2. В методе GetHelperHandle класса TAnimalHelpers заменить TAnimalClass на TClass.
3. В конструкторе TAnimalHelpers.Create() добавить FHelpers.Sorted := True;.
4. Ветку else в TAnimalHelpers.AddHelper заменить на
 else begin
   for i:= 0 to FHelpers.Count - 1 do begin
     Child := THelperHandle(FHelpers.Objects[i]);
     if (Child.Parent = aParent) and
         Child.Owner.InheritsFrom(aClass) then begin
       Child.Parent := Handle;
       exit;
     end;
   end;
   FHelpers.AddObject(aClass.ClassName(), Handle);
   Handle.Parent := aParent;
   Handle.Order := aCallOrder;
 end;

5. В программе объявить {$APPTYPE CONSOLE}

После этого работает.

О цене вопрос некорректен.
Во-первых, я не ставил перед собой цель оптимизации работы.
Во-вторых, большая часть проведённой в программе работы должна будет делаться на этапе компиляции и не на много замедлит производительность.


 
oxffff ©   (2007-04-16 12:42) [99]

euru ©   (16.04.07 02:55) [98]

> > oxffff ©   (13.04.07 12:07) [88]
>
> > Как отличить один класс(без apply helper) и другой класс(с
>
> > apply helper).
> Идея-то как раз и заключается в том, что для разработчика
> название класса и его тип после применения хелпера не изменялись.
>  А если вдруг понадобится информация о наличии в классе
> хелпера, то можно, например, задействовать оператор is.
>
>
> > Для каждого из них будет создана разная VMT(СlassType),
> если
> > вы допускаете возможность override.
> Наличие VMT в откомпилированной программе -- это внутреннее
> представление (способ реализации) полиморфизма классов.
> Как именно будет реализован этот механизм при наличии хелперов,
>  не должно волновать разработчиков. То, что в данной версии
> Delphi тип класса и VMT эквивалентны, является просто следствием
> реализации и не факт, что в последующих версиях это условие
> будет соблюдаться. Вполне возможно, что будет использоваться
> какая-нибудь XMT (eXtended Method Table), в составе которой
> будет информация и о виртуальных методах.


А совместимость c legacy кодом?

Даже если XMT (eXtended Method Table) будет размещена по отрицательным
смещениям от VMT.
Вызовы legacy кода уже привязаны с entry VMT.

Можно даже и из этой ситуации найти выход. Только для чего?

Все что вы хотите можно сделать и текущими средствами. IMHO.


 
euru ©   (2007-04-16 17:31) [100]


> oxffff ©   (16.04.07 12:42) [99]

> А совместимость c legacy кодом?
Неужели в последних версиях Delphi поддерживается совместимость с пакетами ещё из первых версий Delphi? А на уровне исходных кодов остаётся 100% совместимость.
Кстати, про совместимость. В Delphi for .Net отказались от делегирования интерфейсов, ссылаясь на то, что в .Net такого нет. А как же в этом случае совместимость с legacy кодом?


> Можно даже и из этой ситуации найти выход. Только для чего?
> Все что вы хотите можно сделать и текущими средствами. IMHO.
Странно. Почему же тогда разработчики не воспользовались текущими средствами для объединения TObject и Object, а зачем-то ввели какие-то хелперы.


 
oxffff ©   (2007-04-16 18:06) [101]

to euru

> А на уровне исходных кодов остаётся 100% совместимость.


Ой не торопитесь.
Legacy код привязан к VMT entry.
Пример
Существует откомпилированный код(legacy), к которому добавляем DLL
расширения (code with HelperEx).
Как legacy код вызовет именно тот "virtual метод из DLL", если он привязан к конкретному смещению в VMT.
Я не говорю, что сделать нельзя.
Каков ваш вариант?

>Кстати, про совместимость. В Delphi for .Net отказались от делегирования >интерфейсов, ссылаясь на то, что в .Net такого нет. А как же в этом >случае совместимость с legacy кодом?

C native кодом? А разве она должна быть?

>Странно. Почему же тогда разработчики не воспользовались текущими >средствами для объединения TObject и Object, а зачем-то ввели какие-то >хелперы.

Для того, чтобы объединить scope и добавить псевдо-методы. Это позволило провести порт VCL на .NET на порядок меньшими трудозатратами.

если с DMT дело об


 
euru ©   (2007-04-18 17:47) [102]


> oxffff ©   (16.04.07 18:06) [101]

> Существует откомпилированный код(legacy), к которому добавляем
> DLL расширения (code with HelperEx).
Наверно, всё-таки заменяем существующую DLL новой версией. Иначе как откомпилированный код узнает о появлении в его распоряжении новой DLL?


> Как legacy код вызовет именно тот "virtual метод из DLL",
>  если он привязан к конкретному смещению в VMT.
Насколько я знаю, механизм DLL не умеет передавать информацию о классе в программу, использующую эту DLL. Всё, что может получить внешняя программа, - это указатель на область памяти, выделенную под экземпляр класса. Для корректной интерпретации этой области как экземпляра соответствующего класса программа должна обладать дополнительной информацией. Поэтому возможны два варианта использования классов из DLL:
1. программа не использует экземпляры таких классов в явном виде, а взаимодействует с ними посредством экспортируемых из DLL функций;
2. программа использует экземпляры классов из DLL, но для этого должен существовать модуль с описанием этих классов, известный как программе, так и DLL.

В первом варианте прямое взаимодействие программы с экземплярами классов отсутствует. Поэтому, какие бы ни были изменения в реализации классов DLL (в том числе и использование хелперов), на работе программы они не отразятся.
Во втором варианте совместимость в общем случае не гарантирована. Но отсутствие гарантии никак не связана с использованием хелперов. Несовместимости можно добиться и без них. Достаточно, например, в класс добавить ещё один виртуальный метод, и новая версия DLL с большой долей вероятности будет приводить к ошибкам исполнение программы. Поэтому такая несовместимость в качестве аргументации против хелперов, мне кажется, несколько некорректна (такие же аргументы можно привести и против использования обычных экспортируемых из DLL функций).

Кстати, Borland тоже как-то не очень следит за совместимостью со своими пакетами при появлении очередной версии Delphi. Однако активного сопротивления или хотя бы возмущения со стороны разработчиков мной почему-то не наблюдалось.

Но, как возможные варианты решения совместимости, я могу предложить следующие:
1. для каждого класса, в котором выртуальный метод замещён методом из хелпера, в VMT создаётся копия записи оригинального класса, в которой по соответствующему смещению прописывается ссылка на метод хелпера;
2. в VMT класса указатель на оригинальную функцию замещается указателем на функцию-заглушку, которая определяет, какой именно метод должен быть вызван в том или ином случае.


 
oxffff ©   (2007-04-18 18:10) [103]


> Во втором варианте совместимость в общем случае не гарантирована.
>  Но отсутствие гарантии никак не связана с использованием
> хелперов. Несовместимости можно добиться и без них. Достаточно,
>  например, в класс добавить ещё один виртуальный метод,
> и новая версия DLL с большой долей вероятности будет приводить
> к ошибкам исполнение программы.


Соблюдайте правила абстрактного базового класса и никаких неприятностей.
Дополнительные методы аля getInterface или аля AS


> Но, как возможные варианты решения совместимости, я могу
> предложить следующие:
> 1. для каждого класса, в котором выртуальный метод замещён
> методом из хелпера, в VMT создаётся копия записи оригинального
> класса, в которой по соответствующему смещению прописывается
> ссылка на метод хелпера;
> 2. в VMT класса указатель на оригинальную функцию замещается
> указателем на функцию-заглушку, которая определяет, какой
> именно метод должен быть вызван в том или ином случае.


Механизм вызова усложниться + еще один уровень косвенности + проверка.
Что в итоге? Снижение скорости.

И это при учете того, что helperEx может быть востребован в редких случаях при учете того, что разработчик предусмотрит объявление функций virtual или dynamic.

Вы наверно хотите еще и таблицу интерфейсов заменять\дополнять?

-72 Pointer pointer to interface table (or nil)


 
euru ©   (2007-04-22 02:29) [104]


> oxffff ©   (18.04.07 18:10) [103]

> Соблюдайте правила абстрактного базового класса и никаких
> неприятностей. Дополнительные методы аля getInterface или
> аля AS
Как я могу соблюдать эти правила, если Borland практически в каждой версии Delphi вносила изменения в свои компоненты. Большие сомнения у меня, что программа, написанная на Delphi 2, без проблем бы работала с формами и элементами управления, хранящимися в DLL, написанной на Delphi 7.


> Механизм вызова усложниться + еще один уровень косвенности
> + проверка.Что в итоге? Снижение скорости.
Такие же аргументы про усложнение механизма вызова и и снижение скорости были и во времена появления языков ООП. Однако сейчас на это практически не обращают внимание.



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.98 MB
Время: 0.045 c
11-1160059285
ZiTrAX
2006-10-05 18:41
2007.05.20
MaskEdit в KOL/MCK


2-1178002029
Click[Up]
2007-05-01 10:47
2007.05.20
Поиск текст не зависимо от регистра в БД


15-1177249159
ari_9
2007-04-22 17:39
2007.05.20
в каком DB-эксплорере можно сделать sql запрос из двух FB баз ?


15-1176885141
Карелин Артем
2007-04-18 12:32
2007.05.20
Вода из водопровода vs вода из бутыли.


15-1176990214
divisi
2007-04-19 17:43
2007.05.20
Розроботка Игор





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский