- •Объектно-ориентированное программирование
- •Часть 1 классы и объекты
- •Введение
- •1. Классы и объекты
- •Var aLine: tLine;
- •Var aColorLine: tColorLine;
- •2. Методы
- •2.1. Методы-функции и методы-процедуры
- •2.2. Конструкторы и деструкторы
- •Inherited Create;
- •Var TmpFrm: tForm;
- •Var Mem: tMemo;
- •2.3. Классовые процедуры и функции
- •Var s: String;
- •2.4. Скрытый Self
- •3. Видимость компонентов класса
- •4. Наследование
- •4.1. Основные понятия
- •4.2. Наследование полей
- •4.3. Поведение методов при наследовании
- •Var SomeObject: t1;
- •Virtual;
- •Virtual; Abstract;
- •4.4. Иерархия классов
- •4.5. Rtti
- •4.6. Проверка типа
- •4.7. Приведение типа
- •4.8. Указатели на класс
- •Var ObjRef: tObjRef;
- •Implementation
- •X, y, w, h: Integer): tControl;
- •5. Полиморфизм
- •6. Свойства (properties)
- •6.1. Объявление свойств
- •6.2. Объявления свойств-массивов
- •Var I: Byte;
- •6.3. Раздел Read
- •6.4. Раздел Write
- •Inherited Create;
- •Inherited Destroy;
- •6.5. Команды Default, NoDefault и Stored
- •6.6. Команда Index
- •Var aYear, aMonth, aDay: Word;
- •Var aYear, aMonth, aDay: Word;
- •6.7. Команды DispId и Implements
- •6.8. Переопределение свойств при наследовании
- •7. События (events)
- •7.1. Объявление событий
- •IfAssigned(fOnMouseMove) Then fOnMouseMove(Self, Shift, X, y);
- •Vk_return: NumMemo.DoNumStr(l);
- •Vk_return: PostMessage(NumMemo.Handle, wm_user1,1, 0);
- •7.2. Обработчики событий
- •7.3. Делегирование событий
- •Var Objl: tIstClass;
- •7.4. Переопределение стандартных событий
- •Var NewBtn: tNewButton;
6.6. Команда Index
Команда Index используется в связи с методами доступа к нескольким свойствам. Если несколько свойств имеют идентичные методы доступа для чтения и/или записи, то выбор свойства внутри таких методов может быть сделан с помощью оператора Case и значения целочисленного параметра команды Index.
Примечания:
• Эта команда указывается первой в списке команд объявления свойств.
• Методы доступа к свойству, имеющему раздел Index должны иметь дополнительный параметр, объявленный как Integer. Для метода чтения этот параметр должен быть последним в списке параметров функции, а для метода записи этот параметр должен быть предпоследним в списке параметров процедуры - предшествовать параметру, определяющему значение свойства.
Примером может служить приведенный в справочной системе Delphi класс TSampleCalendar.
Type
TSampleCalendar=CIass(TCustomGrid) Private
Function GetDateElement(Index: Integer): Integer;
Procedure SetDateElement(Index: Integer; Value: Integer);
Public
Property Day: Integer Index 3 Read GetDateElement Write SetDateElement;
Property Month: Integer Index 2 Read GetDateElement Write SetDateElement;
Property Year: Integer Index 1 Read GetDateElement Write SetDateElement;
End;
Function TSampleCalendar.GetDateElement(Index: Integer): Integer;
Var aYear, aMonth, aDay: Word;
Begin
DecodeDate(FDate, AYear, AMonth, ADay); // Декодер даты
Case Index Of // Выбор индекса
1: Result:=AYear;
2: Result:=AMonth;
3: Result:=ADay;
Else Result:=-l;
End;
End;
Procedure TSampleCaIendar.SetDateElement(Index: Integer; Value: Integer);
Var aYear, aMonth, aDay: Word;
Begin
If Value > 0 Then Begin
DecodeDate(FDate, AYear, AMonth, ADay); // Декодер даты
Case Index Of // Выбор индекса
1: AYear;=Value;
2: AMonth:=Value;
3: ADay:=Value;
Else Exit;
End;
FDate:=EncodeDate(AYear, AMonth, ADay); // Кодер даты
Refresh;
End;
End;
6.7. Команды DispId и Implements
а) Команда DispID используется для присвоения свойству значения Dispatch ГО, которое применяется в автоматизации OLE. Это целочисленное значение обычно используется при объявлении свойств Dispatch интерфейсов. Эта команда может быть указана только у свойства, объявляемого в разделе Automated класса. Более подробно эта команда будет рассмотрена в главе, посвященной интерфейсам.
б) Команда Implements используется при делегировании полномочий интерфейсов свойству класса. Применяется для реализации классов поддерживающих интерфейсы и будет рассмотрена позднее во второй части пособия в главе, посвященной интерфейсам.
6.8. Переопределение свойств при наследовании
При наследовании свойств можно в классе-потомке заменить унаследованную или добавить отсутствующую команду, изменить видимость и даже
повторно объявить свойство.
а) Для изменения области видимости необходимо в классе-потомке объявить имя свойства без указания типа и команд в разделе с большей видимостью, обычно в Public или Published, т.е. в сторону увеличения видимости.
Public Property MyProperty;
б) Для изменения или добавления команды следует объявить свойство без указания типа с дополнительной и/или измененной командой (Read] Write|Stored|Default|NoDefault). Одновременно можно изменить и область видимости.
в) Для повторного объявления свойства следует указать имя свойства вместе с новым типом. Обязательно должна быть хотя бы одна команда доступа (Read|Write). При переопределении свойства можно вместо старых методов доступа объявить и использовать новые.
Отметим, что переопределение не запрещает доступ к исходному свойству. Путем приведения типов можно обратиться к свойству предка или потомка. При этом будут вызваны методы доступа свойства того класса, объект которого указывается при приведении типов. Таким образом, полиморфизм при доступе к свойству не наблюдается.
Объявим два класса, включающих свойства и методы доступа. При этом во втором классе свойство переопределим заново, изменив одновременно и тип свойства и методы доступа.
Type
TlstClass=Class // Первый класс
FFId: Integer; // Поле целого типа
Function Getint: Integer; // Метод чтения
Procedure Setlnt(lnt: Integer); // Метод записи
Property Prop: Integer Read Getint Write Setint; // Свойство целого типа
End;
T2ndClass=Class(TlstClass) II Второй класс
Function GetStr: String; II Метод чтения
Procedure SetStr(St: String); II Метод записи
Property Prop: String Read GetStr Write SetStr; // Свойство строкового типа
End;
Var Objl: TIstClass; II Переменная первого класса
Obj2: TZndClass; // Переменная второго класса
После объявления реализации указанных методов и инициализации экземпляров указанных классов и допустимы следующие операторы:
Procedure TForml.ButtonlClick(Sender: TObject);
Begin
Editl.Text:=IntToStr(Objl.Prop); II Доступ к свойству 1-го объекта Edit2.Text:=T2ndClass(Obj l).Prop; II Доступ к свойству 1-го объекта
End;
Procedure TFonnl.Button2Click(Sender: TObject);
Begin
Edit3.Text:=Obj2.Prop; II Доступ к свойству 2-го объекта Edit4.Text:=IntToStr(TlstClass(Obj2).Prop); // К свойству 2-го объекта
End;
Procedure TForinl.Button3Click(Sender: TObject);
Begin
Edit5.Text:=T2ndClass(Objl).Prop; II Доступ к свойству 1-го объекта
End;
Третий обработчик показывает, что в поле ввода Edit5 заносится значение свойства строкового типа. Однако с помощью приведения типов вызывается объект первого класса, у которого одноименное свойство имеет целый тип. Тем не менее все корректно работает. Обращение к свойству приводит к вызову соответствующего ему метода.
г) Команда Implements позволяет для наследованных свойств добавить список интерфейсов, не меняя других характеристик свойства.
