Как получить свойства класса в delphi

Поля, свойства и методы

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

При объявлении имен полей принято к названию добавлять заглавную букву F . Например FSomeField.

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

Для получения и передачи данных в классе применяются свойства. Для объявления свойств в классе используется зарезервированное слово property .

Свойства представляют собой атрибуты, которые составляют индивидуальность объекта и помогают описать его. Например, обычная кнопка в окне приложения обладает такими свойствами, как цвет, размеры, положение. Для экземпляра класса "кнопка" значения этих атрибутов задаются при помощи свойств — специальных переменных, определяемых ключевым словом property . Цвет может задаваться свойством Color , размеры — свойствами Width и Height и т. д.

Так как свойство обеспечивает обмен данными с внешней средой, то для доступа к его значению используются специальные методы класса. Поэтому обычно свойство определяется тремя элементами: полем и двумя методами, которые осуществляют его чтение/запись:

type

TAnObject = class(TObject)

function GetColor: TSomeType;

procedure SetColor(ANewValue: TSomeType);

property AColor: TSomeType read GetColor write SetColor;

end;

В данном примере доступ к значению свойства AColor осуществляется через вызовы методов GetColor и SetColor . Однако в обращении к этим методам в явном виде нет необходимости: достаточно написать:

AnObject.AColor := AValue;

AVariable := AnObject.AColor;

и компилятор самостоятельно оттранслирует обращение к свойству AColor в вызовы методов Getcolor или Setcolor . Tо есть внешне свойство выглядит в точности как обычное поле, но за всяким обращением к нему могут стоять нужные вам действия. Например, если у вас есть объект, представляющий собой квадрат на экране, и его свойству "цвет" вы присваиваете значение "белый", то произойдет немедленная перерисовка, приводящая реальный цвет на экране в соответствие со значением свойства. Выполнение этой операции осуществляется методом, который связан с установкой значения свойства "цвет".

В методах, входящих в состав свойств, может осуществляться проверка устанавливаемой величины на попадание в допустимый диапазон значений и вызов других процедур, зависящих от вносимых изменений. Если же потребности в специальных процедурах чтения и/или записи нет, можно вместо имен методов применять имена полей. Рассмотрим следующую конструкцию:

TPropObject = class(TObject)

FValue: TSomeType;

procedure DoSomething;

function Correct(AValue: Integer):boolean;

procedure SetValue(NewValue: Integer);

property AValue: Integer read FValue write SetValue;

end;

.

procedure TPropObject.SetValue(NewValue: Integer);

begin

if (NewValueoFValue) and Correct(NewValue) then EValue := NewValue;

DoSomething;

end;

В этом примере чтение значения свойства AValue означает просто чтение поля rvalue . Зато при присвоении значения внутри SetValue вызывается сразу два метода.

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

type

TAnObject = class(TObject)

property AProperty: TSomeType read GetValue;

end;

В этом примере вне объекта значение свойства можно лишь прочитать; попытка присвоить свойству AProperty значение вызовет ошибку компиляции.

Для присвоения свойству значения по умолчанию используется ключевое слово default :

property Visible: boolean read FVisible write SetVisible default True;

Это означает, что при запуске программы свойство будет установлено компилятором в True .

Свойство может быть и векторным; в этом случае оно внешне выглядит как массив:

property APoints[Index : Integer]:TPoint read GetPoint write SetPoint;

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

Для векторного свойства необходимо описать не только тип элементов массива, но также имя и тип индекса. После ключевых слов read и write в этом случае должны стоять имена методов — использование здесь полей массивов недопустимо. Метод, читающий значение векторного свойства, должен быть описан как функция, возвращающая значение того же типа, что и элементы свойства, и имеющая единственный параметр того же типа и с тем же именем, что и индекс свойства:

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

procedure SetPoint(Index:Integer; NewPoint:TPoint);

У векторных свойств есть еще одна важная особенность. Некоторые классы в Delphi (списки т-List, наборы строк TStrings ) "построены" вокруг основного векторного свойства (см. гл. 7). Основной метод такого класса дает доступ к некоторому массиву, а все остальные методы являются как бы вспомогательными. Специально для облегчения работы в этом случае векторное свойство может быть описано с ключевым словом default :

type

TMyObject = class;

property Strings[Index: Integer]: string read Get write Put; default;

end;

Если у объекта есть такое свойство, то можно его не упоминать, а ставить индекс в квадратных скобках сразу после имени объекта:

var AMyObject: TMyObject;

begin

.

AMyObject.Strings[1] := ‘First’;

AMyObject[2] := ‘Second’; (второй способ>

.

end.

Будьте внимательны, применяя зарезервированное слово default , — как мы увидели, для обычных и векторных свойств оно употребляется в разных случаях и с различным синтаксисом.

О роли свойств в Delphi красноречиво говорит следующий факт: у всех имеющихся в распоряжении программиста стандартных классов 100% полей недоступны и заменены базирующимися на них свойствами. Рекомендуем при разработке собственных классов придерживаться этого же правила.

Внимательный читатель обратил внимание, что при объяснении терминов "поле" и "свойство" мы использовали понятие метода, и наверняка понял его общий смысл. Итак, методом называется объявленная в классе функция или процедура, которая используется для работы с полями и свойствами класса. Согласно принципам ООП (см. разд. "Инкапсуляция" далее в этой главе), обращаться к свойствам класса можно только через его методы. От обычных процедур и функций методы отличаются тем, что им при вызове передается указатель на тот объект, который их вызвал. Поэтому обрабатываться будут данные именно того объекта, который вызвал метод. На некоторых особенностях использования методов мы остановимся ниже.

Как получить свойства класса в delphi

Внутренняя организация объекта должна быть скрыта для внешней стороны, это объектно-ориентированного концепция. Пока вы позволяете полям (данным) в классе быть внешне непосредственно доступными (помещая в public или published разделы), это будет являться, по крайней мере, неблагоразумно. Вместо этого, Property может использоваться, чтобы определить, как данные читаются и написаны.

Версии 1, 2 и 3: Эти основные формы определяют доступ чтения, записи или чтения и записи для полей класса. Данные Type возвращают из поля или метода вызванного Получателем. Данные модифицируются через поле или метод Установщик.

Обратите внимание, что Вы должны использовать отличное название для Name от «Getter» и «Setter«. Например: Property Age read fAge write fAge; Вы можете использовать имена полей, когда не требуется обработка поиска и проверки. При использовании метода чтения или записи, считанное или записанное значение могут быть намного более просты, чем сохраненное значение. Сохраненное значение может быть полностью различным.

Версии 4, 5 и 6: Использование ключевого слова Index говорит Delphi, чтобы он передал значение Constant как параметр методов Получателя и Установщика. Они должны быть функциями, которые получают это постоянное индексное значение как параметр.

Например: Property Item2 : string Index 2 read ItemGetter; где ItemGetter определен как: Function ItemGetter(Index : Integer) : string; Значение Default обеспечивает информацию для свойства во время выполнения. NoDefault — нет. Stored находится вне области основ Delphi.

Версии 7, 8 и 9: Это — обобщенная версия версий 4,5 и 6. Она просит пользователя указать индексное значение для методов Getter и Setter.

Default позволяет вызовам метода Getter и Setter быть замененными как в следующем примере: myValue := MyClass.Getter(23); может быть заменено : myValue := MyCLass[23];

Версия 10: Позволяет реализации Интерфейс(Interface) метода быть делегированной в свойство. Доступ к свойству, вызывает выполнение интерфейса.

Версия 11: Повторно объявляя свойство родительского класса, вы можете сделать так в public или published пункте, таким образом, поднимая права доступа свойства.

Private Начинает частный (Private) раздел данных и методов в классе

Protected Начинает раздел класса частных данных доступных подклассам

Как получить свойства класса в delphi


aleshap   ( 2004-10-12 10:16 ) [0]

Уважаемые мастера!
Каким образом можно получить список всех свойств класса из области public?
При использовании RTTI получается получить доступ только к published свойствам.

var TD:PTypeData;  
   List:PPropList;
   i,N:Integer;
begin
  TD:=GetTypeData(CInfo.ClassInfo);
  N:=TD.PropCount;
  if N<=0 then exit;
  GetMem(List,SizeOf(PPropInfo)*N);
try
  GetPropInfos(TObject(TD).ClassInfo ,List);
  for i:=0 to N-1 do begin
    Memo.Lines.Add(List[i].Name);
  .

Ведь Delphi же их как то получает?
Спасибо


aleshap   ( 2004-10-12 10:34 ) [1]

НИКАК!
Все вопрос снят! Спасибо за участие


TUser ©   ( 2004-10-12 10:38 ) [2]

published — это и есть такой механизм, который описывает информацию доступную, через RTTI. Все что не-published через RTTI недоступно (в смысле — все свойства класса).

Delphi — у него есть компилятор, он исходники читает.


Sapersky   ( 2004-10-12 10:47 ) [3]

Каким образом можно получить список всех свойств класса из области public?

Урок 60 — Свойства классов Delphi, (часть 2/5)

В этом уроке мы продолжаем изучать классы и в этом уроке мы разберёмся в их свойствах.

Поля данных, исходя из принципа инкапсуляции — одного из основополагающих в объектно-ориентированном программировании, всегда должны быть защищены от несанкционированного доступа. Доступ к ним, как правило, должен осуществляться только через свойства, включающие методы чтения и записи полей. Поэтому поля целесообразно объявлять в разделе private — закрытом разделе класса. В редких случаях их можно помещать в protected — защищенном разделе класса, чтобы возможные потомки данного класса имели к ним доступ. Традиционно идентификаторы полей совпадают с именами соответствующих свойств, но с добавлением в качестве префикса символа F.

Свойство объявляется оператором вида:

Если в разделах read или write этого объявления записано имя поля, значит предполагается прямое чтение или запись данных (т.е. обмен данными непосредственно с полем).

Если в разделе read записано имя метода чтения, то чтение будет осуществляться только функцией с этим именем. Функция чтения — это функция без параметра, возвращающее значение того типа, который объявлен для свойства. Имя функции чтения принято начинать с префикса Get, после которого следует имя свойства.

Если в разделе write записано имя метода записи, то запись будет осуществляться только процедурой с этим именем. Процедура записи — это процедура с одним параметром того типа, который объявлен для свойства. Имя процедуры записи принято начинать с префикса Set, после которого следует имя свойства.

Если раздел write отсутствует в объявлении свойства, значит это свойство только для чтения и пользователь не может задавать его значение.

Директивы запоминания определяют, как надо сохранять значения свойств при сохранении пользователем файла формы .dfm. Чаще всего используется директива default — значение по умолчанию.
Она не задает начальные условия. Это дело конструктора. Директива просто говорит, что если пользователь в процессе проектирования не изменил значение свойства но умолчанию, то сохранять значение свойства не надо.

Начните новый проект. Объявление класса, который мы хотим создать, можно поместить непосредственно в файл модуля. Но если вы хотите создать класс, который будете использовать в различных проектах, лучше оформить его в виде отдельного модуля unit, сохранить в каталоге своей библиотеки или библиотеки Delphi, и подключать в дальнейшем к различным проектам с помощью предложения uses. Мы выберем именно этот вариант. Так что выполните команду File | New | Unit (в некоторых более старых версиях Delphi — File | New и на странице New выберите пиктограмму Unit). Сохраните сразу этот ваш модуль в библиотеке под именем, например, MyClasses. А в модуль формы введите оператор, ссылающийся на этот модуль:

Теперь займемся созданием класса в модуле MyClasses. Текст этого модуля может иметь пока такой вид:

Вглядимся в приведенный код. Интерфейсный раздел модуля interface начинается с предложения uses. Заранее включать это предложение в модуль не требуется. Но по мере написания кода вы будете встречаться с сообщениями компилятора о неизвестных ему идентификаторах функций, типов и т.п. Столкнувшись с таким сообщением, надо посмотреть во встроенной справке Delphi или в справке [3], в каком модуле объявлена соответствующая функция или класс. И включить этот модуль в приложение uses.

Теперь обратимся к объявлению класса. Объявленный класс TPerson наследует непосредственно классу TObject, поскольку родительский класс не указан. В закрытом разделе класса private объявлен ряд полей. Поле FName предполагается использовать для фамилии, имени и отчества человека. Поля FDepl, FDep2, FDep3 будут использоваться под указание места работы или учебы. Поле FYear будет хранить год рождения, поле FSex — указание пола: символ «м» или «ж». Поле FAttr будет хранить какую-то характеристику: штатный — нештатный, отличник или нет и т.п. Поле FComment предназначено для каких-то текстовых комментариев. В частности, в нем можно хранить свойство Text многострочного окна редактирования Memo или RichEdit. Так что это может быть развернутая характеристика человека, правда, без форматирования.

В открытом разделе класса public объявлены свойства, соответствующие всем полям. Чтение всех свойств осуществляется непосредственно из полей. Запись во всех свойствах, кроме Sex, осуществляется тоже непосредственно в поля. А для поля Sex указана в объявлении свойства процедура записи SetSex, поскольку надо следить, чтобы по ошибке в это поле не записали символ, отличный от «м» и «ж». Соответственно в защищенном разделе класса protected содержится объявление этой процедуры. Как говорилось ранее, она должна принимать единственный параметр типа, совпадающего с типом свойства.

В раздел модуля implementation введена реализация процедуры записи SetSex. Ее заголовок повторяет объявление, но перед именем процедуры вводится ссылка на класс TPerson, к которому она относится. Не забывайте давать такие ссылки для методов класса. Иначе получите сообщение компилятора об ошибке; Unsatisfied forward or external declaration: TPerson.SetSex — нереализованная ранее объявленная или внешняя функция TPerson.SetSex.

Тело процедуры SetSex в особых комментариях не нуждается. В нем проверяется допустимость символа, переданного в процедуру через параметр Value. Если символ допустимый, то его значение заносится в поле FSex. Это поле, как и другие закрытые поля, открыто для методов данного класса. При ошибочном символе пользователю выдается сообщение об ошибке. Правда, лучше было бы в этом случае сгенерировать исключение, но пока мы не обсуждали, как это можно делать.

Вы создали класс в вашем модуле MyClasses. Давайте посмотрим, как можно использовать объекты нашего класса. Создайте в модуле формы Unit1 вашего приложения тест класса TPerson. Введите в модуль операторы:

uses Classl;
var Pers: TPerson;

Они обеспечивают связь с модулем, описывающим класс, и объявляют переменную Pers, через которую вы будете связываться с объектом класса. Но так же, как при работе с другими объектами и записями, объявление этой переменной еще не создает сам объект. Это указатель на объект, и его значение равно nil.

Создание объекта вашего класса TPerson должно осуществляться вызовом его конструктора Create. Так что создайте обработчик события OnCreate вашей формы, и вставьте в него оператор:

Вот теперь объект создан, и переменная Pers указывает на него. Чтобы не забыть очистить память от этого объекта при завершении работы приложения, сразу создайте обработчик события OnDestroy формы, и вставьте в него оператор:

Почему ваш объект воспринимает методы Create и Free? Ведь вы их не объявляли в классе TPerson! Это работает механизм наследования. В классе TObject, являющемся родительским для TPerson, методы Create и Free имеются. А поскольку вы их не перегружали, то ваш класс наследует их.

Теперь перенесите на форму четыре окна Edit, окно Memo и две кнопки. Пусть первая кнопка с надписью Запись заносит в объект Pers данные из окон редактирования: ‘ фамилию с именем и отчеством, пол, подразделение, в котором работает или обучается человек, год рождения, характеристику из окна Memo. Обработчик щелчка на ней может иметь вид:

А вторая кнопка с надписью Чтение пусть осуществляет чтение информации из объекта в окна редактирования. Обработчик щелчка на ней может иметь вид:

Выполните ваше приложение. Занесите в окна редактирования какую-то подходящую информацию и щелкните на кнопке Запись. А потом сотрите тексты всех окон редактирования и щелкните на кнопке Чтение. Информация в окнах должна восстановиться. Проверьте также реакцию на неверный символ, задающий пол.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *