Перейти на главную   
  helloworld.ru - документация и книги по программированию  
helloworld.ru - документация и книги по программированию
    главная     хостинг    
Поиск по сайту:  
Смотрите также
Языки программирования
C#
MS Visual C++
Borland C++
C++ Builder
Visual Basic
Quick Basic
Turbo Pascal
Delphi
JavaScript
Java
PHP
Perl
Assembler
AutoLisp
Fortran
Python
1C

Интернет-технологии
HTML
VRML
HTTP
CGI
FTP
Proxy
DNS
протоколы TCP/IP
Apache

Web-дизайн
HTML
Дизайн
VRML
PhotoShop
Cookie
CGI
SSI
CSS
ASP
PHP
Perl

Программирование игр
DirectDraw
DirectSound
Direct3D
OpenGL
3D-графика
Графика под DOS

Алгоритмы
Численные методы
Обработка данных

Сис. программирование
Драйверы

Базы данных
MySQL
SQL

Другое

Хостинг


Друзья
demaker.ru
Реклама

Лучший хостинг. Аренда серверов




helloworld.ru

Turbo/Borland Pascal --> Delphi FAQ (часть 2)

     (2) //Свойства и события. Динамическое задание событий.
     Q: Что такое Self?
     Q: Что такое свойство (property)?
     Q: Чем, на самом деле, является событие (event)?
     Q: Почему компилятор ругается на попытку задать  свои  обработчики
событий для TApplication: Application.OnActivate := MyProcedure; ?

     И опять-таки,  начнем  с определений.  К сожалению,  нередко среди
программистов можно встретить недопонимание того,  что  такое  "метод".
Это понятие  уже  встречалось в ответе (1),  и там оно использовалось в
общепринятом смысле:  метод -- это функция или  процедура,  которую  мы
описываем внутри класса.  Все так,  однако, при таком понимании вопроса
от нашего внимания ускользает важный аспект:  чем отличается процедура,
описанная внутри класса (то есть,  метод) и процедура описанная "просто
так", например, внутри секции Implementation?
     Заметим, что  машинный код любого метода размещается в памяти лишь
один раз,  вне зависимости от того,  сколько экземпляров данного класса
мы создали.  Однако метод должен,  как минимум,  работать с конкретными
значениями полей,  т.е.  с конкретным объектом!  А значит, метод должен
"уметь"  как-то  "узнавать"  какой  объект его вызвал.  Раз так,  то не
удивительно,  что "внутрь" любого метода всегда,  "неявно",  передается
указатель на объект,  который вызывает этот метод. Этот указатель носит
имя  Self,  который,  быть  может  Вами  уже  когда-нибудь  встречался.
Естественно,  в обычную процедуру подобный указатель не передается! Вот
в   этом   и   заключается   важное   отличие   просто   процедуры,   и
процедуры-метода.
     Это половина  того,  что  нам необходимо знать для осознания того,
что такое Event.  Вторая требуемая половина  --  это  понятие  Property
(свойство).  Как  гласит  старинный принцип ООП,  все действия с полями
объекта  должны  осуществляться  только  через  методы  этого  объекта.
Property   --   практическое  воплощение  этого  принципа.  Стандартное
описание свойства (Property):
     property MyValue:Integer read GetValue write PutValue;
определяет, что чтение целочисленной (Integer) величины  MyValue  будет
осуществляться через функцию
     function GetValue:Integer;
а запись -- будет производится процедурой
     procedure PutValue(Value:Integer);
Разумеется функция  GetValue  и  процедура PutValue должны быть описаны
как методы того же класса.  После подобного описания свойства  MyValue,
команда  MyObject.MyValue:=10;  вызовет процедуру PutValue с параметром
10.  Разумеется,  переданное процедуре значение  желательно  сохранять,
поэтому стандартный вид процедуры PutValue:
     procedure TMyObject.PutValue(Value:Integer);
     begin FValue:=Value; {Любые дополнительные действия} end;
где FValue --  поле  класса  TMyObject,  определенное,  как  правило  в
private  секции  (чтобы  быть недоступной "пользователю").  Аналогичные
действия  происходят  и  при  обращении  ResultValue:=MyObject.MyValue.
Соответственно, функция GetValue описывается как
     function TMyObject.GetValue:Integer;
     begin Result:=FValue; {Любые дополнительные действия} end;
     В итоге, мы добились упомянутого выше принципа: вся работа с полем
FValue   происходит   через   методы   нашего   класса   (более   того,
"пользователь"  даже  не  догадывается о существовании поля FValue,  он
работает только со свойством Value).  Таким образом, принцип-принципом,
но  такой  подход  позволяет  скрыть  от  других  людей  методы и поля,
представляющие собой внутреннее устройство класса.  К тому же, это дает
и немалую практическую пользу, например, если значение свойства связано
с какими-то другими характеристиками класса (объекта),  которые  должны
меняться при изменении самого свойства (примером может служить свойства
left и top большинства (если не  всех)  контролов,  изменение  значений
которых автоматически влечет изменения положения контрола).
     Если же чтение или запись должны осуществляться прямо из/в какого-
то поля без каких-либо "дополнительных действий",  то допускается такое
определение свойства:
     property MyValue:Integer read FValue write FValue;
     Итак, что же такое event?  Hа самом деле,  не более,  чем свойство
процедурного типа:
     private
       FOnChange: TNotifyEvent;
     public
       property OnChange:TNotifyEvent read FOnChange write FOnChange;
где TNotifyEvent это процедурный тип. А именно
     TNotifyEvent = procedure(Sender: TObject) of object;
Вроде бы  все  должно быть ясно,  за исключением одного обстоятельства:
что означает "приписка" of object?  Для этого  вспомним  начало  нашего
обсуждения:  раз эта процедура будет работать с конкретным объектом, то
"внутрь" нее должен передаваться указатель на объект,  тот самый  Self.
Так  вот,  of  object  объявляет  новый процедурный тип,  как тип таких
процедур,  в которых передается указатель  на  объект.  Именно  поэтому
недопустимо   присваивание  вроде  Application.OnActivate:=MyProcedure,
если MyProcedure не описана как метод какого-нибудь  класса (компилятор
будет   выдавать   ошибку   из-за   несоответствия  типа  присваиваемой
процедуры).  Более того,  на момент присваивания объект того класса,  в
котором  описана  MyProcedure  должен  быть  уже создан!  Иначе попытка
присваивания приведет к AV.
     Как правило,   (если   речь   идет  о  переопределении  событий  у
Application) такую  процедуру описывают внутри главной формы проекта, а
само присваивание производят внутри обработчика события  OnCreate  этой
формы. Хорошей альтернативой служит такой вариант  задания собственного
обработчика события для Application, прямо внутри dpr-файла:
     type TActivateEvent = class
          public
            procedure MyActivate(Sender:TObject);
          end;
     begin
      with TActivateEvent.Create do
       begin
        Application.OnActivate:=MyActivate;
        Application.Initialize;
        //..... создание форм
        Application.Run;
        Free
       end
     end;
[ Назад ]









helloworld.ru © 2001-2021
Все права защищены
Rambler's Top100