Приведение классов в Delphi

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

procedure TForml.ButtonlClick(Sender: TObj ect); begin end;

Как мы уже разобрались, в качестве параметра процедура получает указатель на компонент, который сгенерировал событие. Давайте используем этот указатель для того, чтобы изменить свойства класса кнопки. Если вы попробуете написать сле­дующий код:

Sender.Top: = 100 ;

произойдет ошибка. Это вы точно знаете, что данный обработчик события сра­батывает на кнопку, потому что вы создали его именно для кнопки. А вот компиля­тор даже не пытается это узнать. Он видит, что переменная sender имеет тип TObject, а у этого класса нет свойства тор, поэтому произойдет ошибка.

 

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

 

Начнем с варианта, который можно встретить в большинстве книг:

 

if Sender is TButton then

(Sender as TButton).Top:=100;

 

В первой строке проверяем, является ли переменная sender классом TButton. Для этого используется оператор is. Слева от оператора пишется переменная, ко­торую нужно проверить, а справа класс. Если переменная является экземпляром указанного класса, то результатом is будет истина, а значит, выполнится вторая строка кода.

 

Во второй строке кода самое интересное находится в скобках, где мы говорим, что переменная sender должна восприниматься как класс TButton. Для этого ис­пользуем оператор as. Теперь, когда мы явно указали, что перед нами объект кноп­ка, мы можем использовать свойство тор.

 

На самом деле, если посмотреть на иерархию компонента кнопки, то вы увиди­те, что свойство тор наследуется от класса TControi. Это значит, что мы можем безболезненно обратиться к свойству, указывая TControi:

 

if Sender is TControi then

(Sender as TControi).Top:=100;

 

Это уже лучше. Теперь, если на форму поместить еще один компонент, и в об­работчик события onclick установить этот же обработчик события, то все будет работать без проблем. Убедимся? Давайте. Поместим на форму еще одну кнопку TBitBtn со вкладки Additional (Дополнительно). Теперь на вкладке Events (Собы­тия) установим в качестве обработчика onclick уже созданную ранее процедуру Buttoniciick. Для этого выберите ее имя из ниспадающего списка.

 

Несмотря на то, что это совершенно другая кнопка (другой класс), все будет ра­ботать без проблем. По какой бы кнопке вы не кликнули, та и опустится на рас­стояние 100 пикселов.

А теперь еще один интересный трюк. А что если обратиться к свойству caption? Но при этом привести класс не к кнопке, а к TLabel:

(Sender as TLabel).Caption:='OK';

Такой трюк завершится ошибкой. Дело в том, что оператор as приводит класс, и если классы абсолютно разные, то приведение станет невозможным и произойдет ошибка. Что значит разные классы? Если попытаться привести TBitBtn к TButton, ТО не возникнет проблем, потому ЧТО TBitBtn как раз И происходит ОТ TButton. Если привести TBitBtn к TControi, то тоже не возникнет проблем, потому что TControi является одним из предков. Но кнопка не имеет среди своих предков класс TLabel, а значит, нельзя эти два класса привести друг другу.

 

Но все же есть один фокус:

TLabel(Sender).Caption:='OK';

Здесь мы приводим кнопку, которая будет указана в переменной sender, к клас­су TLabel с помощью неявного приведения, которое мы уже рассматривали выше в этой главе. Вот такой трюк пройдет, несмотря на то, что классы совершенно раз­ные. Дело в том, что при таком приведении компилятор всего лишь проверяет, есть ли свойство caption у класса, к которому мы приводим. Если да, то компиляция пройдет удачно. Во время выполнения приведения типов не будет. Программа только будет искать нужное свойство и, если найдет, будет его использовать, по­этому данный код будет корректным.

dle

Помоги проекту! Расскажи друзьям об этом сайте: