![]() |
Главная Случайная страница Контакты | Мы поможем в написании вашей работы! | |
|
Предположим, вы делаете компонент для доступа к данным, например, потомок класса TTable. Допустим, в этом компоненте анализируется список таблиц, имеющихся в базе данных, и по каким-либо признакам (например, наличие поля определенного типа и с определенным именем) выбирается одна для работы. Для нормальной работы компонента имя этой таблицы должно заноситься в свойство TableName. Но это свойство отображается в инспекторе объектов! Программист, использующий этот компонент, может изменить его значение на этапе разработки, что, предположим, сделает компонент неработоспособным. И он будет прав! Если какие-то из свойств или событий нельзя изменять, они должны быть скрыты.
Мы продолжим работу над компонентом TListAdd и в качестве модельной задачи уберем из инспектора объектов свойство Cursor. Это свойство определено в секции published в классе TСontrol и отображается в инспекторе объектов для TListAdd с самого начала разработки компонента. Исходя из этого можно попытаться переопределить данное свойство в секции protected. Компилятор разрешит такое переопределение, но к желаемому результату это не приведет: свойство Cursor как было, так и останется в инспекторе объектов… Любое свойство, будучи однажды определенным в секции published, будет всегда отображаться в инспекторе объектов для всех потомков данного класса.
Для скрытия свойства из инспектора объектов используем две возможности компилятора Delphi, а именно:
1. При объявлении нового свойства с именем, совпадающем с именем уже имеющегося свойства, ранее определенное свойство «затеняется».
2. Свойства, которые имеют доступ только для чтения или только для записи, не отображаются в инспекторе объектов, даже если они объявлены в секции published.
Перед началом работы по скрытию свойства Cursor полезно удалить компоненты TListAdd с формы, иначе может произойти исключение при чтении ресурса формы. Итак, в секции private объявляем переменную FDummy:integer (имя и тип переменной могут быть любыми) и в секции published определяем новое свойство:
property Cursor:integer read FDummy;
Новое свойство обязано называться Cursor, тип его обязан совпадать с типом переменной, определенной выше, свойство должно быть только на чтение или только на запись. После компиляции компонента с помощью редактора пакетов следует вновь поместить компонент TListAdd на форму. Можно обнаружить, что свойство Cursor уже не отображается в инспекторе объектов.
Теперь немного усложним задачу. Предположим, необходимо, чтобы курсор был показан не в виде стрелки, а в виде песочных часов (crHourGlass). Для того чтобы изменить значение свойств по умолчанию, новое значение необходимо присвоить переменной в конструкторе. При попытке в конструкторе присвоить новое значение Cursor
Cursor:=crHourGlass;
компилятор Delphi выдаст диагностическое сообщение о том, что нельзя назначить новое значение переменной, предназначенной только для чтения. Если сделать новое свойство «только для записи», то компилятор выдаст уже другое диагностическое сообщение – о несопоставимых типах данных. Если же объявить переменную FDummy:TCursor и сделать ее доступной только для записи, то компилятор разрешит данное присвоение, но при этом вид курсора не изменится: он по-прежнему будет стрелкой.
Тривиальное решение данной проблемы – объявить класс-потомок TCustomPanel, в конструкторе которого нужно присвоить новое значение переменной Cursor, а от него уже производить наш компонент TListAdd. У такого решения имеется два недостатка:
1. Оно ресурсоемко – размножаются виртуальные методы.
2. Свойство мы прятали в инспекторе объектов от программиста, который будет использовать данный компонент. Мы же хотим работать с данным свойством.
Поэтому решение данной задачи выглядит следующим образом: в конструкторе TListAdd объявляем оператор:
inherited Cursor:=crHourGlass;
Этого достаточно для изменения курсора.
Ранее мы пользовались служебным словом inherited только для вызова метода предка. Данная конструкция позволяет глубже понять значение inherited как обращение к классу-предку. Можно обращаться и к свойствам, и к методам. При обращении к свойству его можно как читать, так и присваивать ему новое значение; при этом служебное слово inherited стоит слева от знака присваивания. Аналогично можно вызывать скрытые методы предка. Обращения по иерархии выше, чем класс-предок, запрещено — конструкция
inherited inherited Cursor:=crHourGlass;
не будет скомпилирована.
На этом будем считать данный проект завершенным. В новом компоненте мы перехватили сообщение, редекларировали свойства, добавили новые свойства и события, спрятали ранее объявленное свойство. Все эти способы применяются для создания компонентов. Ниже мы рассмотрим еще один интересный способ.
Дата публикования: 2015-02-18; Прочитано: 335 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!