Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Hello, World!
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  15:05[Войти] | [Зарегистрироваться]

Обсуждение материала
Self, Sender и events - ЧаВо
Полный текст материала


Другие публикации автора: Levko

Цитата или краткий комментарий:

«... Идея написать эту статью возникла у меня после появления на Круглом столе очередного вопроса вида "У меня есть компонент, у него есть событие On... Что ему нужно присвоить чтоб оно работало?" ...»


Важно:
  • Страница предназначена для обсуждения материала, его содержания, полезности, соответствия действительности и так далее. Смысл не в разборке, а в приближении к истине :о) и пользе для всех.
  • Любые другие сообщения или вопросы, а так же личные эмоции в адрес авторов и полемика, не относящаяся к теме обсуждаемого материала, будут удаляться без предупреждения авторов, дабы не мешать жителям нормально общаться.
  • При голосовании учитывайте уровень, на который расчитан материал. "Интересность и полезность" имеет смысл оценивать относительно того, кому именно предназначался материал.
  • Размер одного сообщений не должен превышать 5К. Если Вам нужно сказать больше, сделайте это за два раза. Или, что в данной ситуации правильнее, напишите свою статью.
Всегда легче осудить сделанное, нежели сделать самому. Поэтому, пожалуйста, соблюдайте правила Королевства и уважайте друг друга.



Добавить свое мнение.

Результаты голосования
Оценка содержания

  Содержит полезные и(или) интересные сведения
[1]550%
 
  Ничего особенно нового и интересного
[2]220%
 
  Написано неверно (обязательно укажите почему)
[3]330%
 
Всего проголосовали: 10

Оценка стиля изложения

  Все понятно, материал читается легко
[1]325%
 
  Есть неясности в изложении
[2]433.3%
 
  Непонятно написано, трудно читается
[3]541.7%
 
Всего проголосовали: 12




Смотрите также материалы по темам:
[Обработчики событий] [Процедуры и функции] [Методы]

Комментарии жителей
Отслеживать это обсуждение

Всего сообщений: 9

13-08-2009 12:02
Прочел, статья отличная! Примеры толковые, положил в свою копилку знаний! )))


28-07-2009 10:27
Какая-то каша из-за непонимания ООП и притягивания за уши кривых решений.
Я бы рекомендовал автору изучить книжку "Паттерны проектирования" банды четырёх, чтобы его советы не вели "новичков" в заведомо неправильном направлении при создании приложений.


23-07-2009 18:27
>>> Но есть в этом способе одна небольшая неудобность. И вот какая. Наш подставной класс не несет никакой смысловой нагрузки (ведь мы его таким спроектировали); более того, скорее всего он будет содержать кучу методов для обработки самых разных событий множества различных обьектов.

Можно:
1. Вынести часто используемые обработчики в отдельный модуль.
2. Сгруппировать логически связанные обработчики по отдельным классам. Появляется смысловая нагрузка для класса: разбивка обработчиков на логически связанные группы.

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

Не надо ни создавать, ни уничтожать. В некотором приближении метод можно рассматривать как совершенно отдельную функцию, и эта функция никак не связана с объектом, а знает о своём экземпляре класса только через параметр Self. Если Self внутри этой функции не используется, то функции совершенно безразлично, существует "её" объект или нет.

>>> И ради чего всё это? Ради одного факта приналежности процедуры обьекту?

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

>>> Возникает желание искать другие пути написания обработчиков. Я предлагаю еще два. Первый. Если Self нам не нужен, тогда самое время вспомнить о методах класса. Их можно вызывать, не создавая экземпляра класса, и в тоже время они пренадлежат классу.

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

Способ второй. Мы уже знаем, что обычная процедура и метод отличаются отсутсвием или наличием скрытого параметра Self. А что, если определить его в статической процедуре?
procedure MyEvent(Self, Sender: TObject; Param: string);
<...>
Но не тут-то было. Любые попытки назначить эту процедуру в качестве обработчика вызывали отчаяное сопротивление компилятора в виде Invalid typecast.


Ну ещё бы... У них же даже размер разный...
Указатель на обычную процедуру - 4
Указатель на метод - 8
Почему? А потому, что указатель на метод, кроме собственно указателя на функцию, содержит ещё и указатель на объект... Тот самый, который будет передаваться в этот метод в качестве параметра Self... Проверить очень легко:

type
  P1 = procedure;
  P2 = procedure of object;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(IntToStr(SizeOf(P1)));     // 4
  ShowMessage(IntToStr(SizeOf(P2)));     // 8
end;


>>> Но решение и здесь оказалось тривиальным:
>>> @t.OnEvent:=@MyEvent;

Ну, приложив достаточную силу, можно ещё и не такое сотворить...

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

Ну, это уже лучше... Но моё предложение более конкретно: при назначении внешних обработчиков всегда делать обработчик обычным методом класса и не использовать внутри него Self.
Пример:

unit Edit_Util;

interface

uses StdCtrls, Graphics;

type
  { Класс предназначен для назначения обработчиков событий
    Экземпляры класса не создавать. Self не использовать }

  TEditEvents = class
  public
    procedure OnEditEnter(Sender: TObject);
    procedure OnEditExit(Sender: TObject);
  end;

implementation

procedure TEditEvents.OnEditEnter(Sender: TObject);
begin
  (Sender as TEdit).Color := clLime;
end;

procedure TEditEvents.OnEditExit(Sender: TObject);
begin
  (Sender as TEdit).Color := clWindow;
end;

end.

Использование:

implementation

uses Edit_Util;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  for i := 0 to ControlCount - 1 do
    if Controls[i] is TEdit then
      with Controls[i] as TEdit do
      begin
        OnEnter := TEditEvents(nil).OnEditEnter;
        OnExit := TEditEvents(nil).OnEditExit;
      end;
end;



23-07-2009 14:18
Молодец Левко!!!
Отличная статья, так держать!
 Zeus


22-07-2009 06:57
>>> CTestClass = class(TObject)
Классы в Delphi принято называть с буквы T. Нет, компилятору конечно все-равно, ему хоть _dSA2fJ21_uIIow подставь, но только будет ли с этого кому-нибудь польза? Для некоторых случаем имеет смысл отступать от этой нормы (исключения, например, начинаются с буквы E), но такой подход неприемлем для статьи для новичков.
>>> Самые любопытные лезли в недра компонента
Новички, которые задают вопросы? Лезли в исходники VCL? Не смешите мои подковы (или что там у змей вместо подков)! Они даже у Гугля стесняются спросить.
>>> Впишем в тело DoEvent строку writeln(Self.FText), а в тело программы после создания t строки
А нельзя было сразу написать готовый код, а не напрягать извилину (я не описался - извилину) и думать, а не просто заниматься копипастой.
>>> поставим на вторую строку брейкпойнт
Я тут с одним, особо продвинутым программистом общался по Аське... от фразы "поставь брейкпойнт на строку 71" его стало рвать совершенно невменяемыми фразами. После некоторого времени (в том числе наблюдений за его действиями удаленно) я понял, что он просто не знает, что такое брейкпойнт.
>>> открываем View->Debug Windows->CPU (Ctrl+Alt+C)
Для новичков - поподробнее, что такое регистры. И что там еще за цикверки и буковки непонятные написаны. Ах да, если новичок продвинутый (нонсенс?) он вспомнит, что параметры передаются через стек (кстати, что это такое?). Про модели вызова ничего не сказано. Да, найти в справке их не представляет сложности (для меня), но для некоторых является проблемой даже понять, ГДЕ надо объявлять переменные в программе на Паскале.
>>> поэтому он может спокойно использовать Self внутри методов
Надо еще уточнить - использовать Self явно в большинстве случаев НЕ НУЖНО! Потому что за... надоели программы, где "затуманенно" написаны вещи типа Self.Left:=Self.Left+10;
>>> полям и другим методам класса-владельца вызванного метода
Можно вопрос - что означает "класс-владелец" в этом контексте?
>>> здесь же содержится первый, классический, вариант назначения событию собственного обработчика
Классический вариант (на мой, сугубо любительский взгляд) - это кинуть компонент на форму, ткнуть дважды в нужный ивент в Object Inspector и набить в открывшемся редакторе кода ShowMessage('Hello, world!');
>>> @t.OnEvent:=@MyEvent;
Ой, плохому учите. Тем более, новичков. Понятно, что когда я пользуюсь объявлением procedure ThreadProc(var Data:TThreadData); где TThreadData=record...end; и потом запускаю поток через BeginThread(...,@ThreadProc,...);, то я хотя бы понимаю, чем это может грозить. А вот новички, они дров наломают.
>>> только когда совсем нет возможности сделать процедуру методом
Можно вопрос, при КАКИХ условиях такой возможности не будет. Ну никак не могу придумать. Честно!


22-07-2009 06:21
Статья неплохая, но не для новичков, (статические методы, работа с указателями) и вообще, зачем учить молодеж плохому ;), последний пример вообще... идеологически некорректный чтоли? ИМХО конечно.  В исходники неплохо-бы комментарии. Хотя, в целом прикольно...


20-07-2009 08:08
Статья - не для новичков. Стиль изложения не очень удачный, хотя сам материал довольно интересен - кто не знал, узнает, кто знал - вспомнит.


20-07-2009 06:34
Не совсем понятно, на какой, собственно, вопрос новичков отвечает столь непростая статья. Отсюда и сложности восприятия.

На вопрос про "Self, Sender, Event" я бы отвечал диаграммами и простыми примерами про ТГрузовик=class(ТАвтомобиль), а не отладчиком и указателями.


20-07-2009 06:20
Для новичков консоль с событиями!?

На вопрос как вызвать отвечать: так и вызывать OnClick(Self).


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
"Мы с тобой одной крови — ты и я!". Чьи это заветные слова?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.

Оценка содержания
 
Содержит полезные и(или) интересные сведения
 
Ничего особенно нового и интересного
 
Написано неверно (обязательно укажите почему)


Оценка стиля изложения
 
Все понятно, материал читается легко
 
Есть неясности в изложении
 
Непонятно написано, трудно читается

Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования