- •Глава 1
- •Структура модуля
- •Интерфейс
- •Реализация
- •Инициализация и завершение
- •Ключевые слова
- •Ключевое слово const
- •Ключевое слово type
- •Комментарии
- •Переменные
- •Типы данных и переменные
- •Преобразование типов
- •Знаки операций
- •Константы
- •Массивы
- •Одномерные массивы
- •Многомерные массивы
- •Функции Low и High
- •Динамические массивы
- •Короткая строка
- •Длинная строка
- •Операции со строками
- •Разбиение литерала по строкам программы
- •Строковые функции
- •Множества
- •Совместимость типов данных
- •Примечание.
- •Указатели
- •Статические и динамические переменные
- •Размещение динамических переменных
- •Разыменование указателя
- •Глава 2.
- •Вложенные условия. Операторы if могут быть вложены друг в друга произвольное число раз:
- •Элементы структуры цикла
- •Цикл for…
- •Цикл for с увеличением счетчика синтаксически определен как
- •Цикл for с уменьшением счетчика в общем случае имеет следующий вид
- •Функции Pred и Succ
- •Цикл while
- •Синтаксис цикла while имеет вид
- •Цикл repeat
- •Управление циклами
- •Оператор goto
- •Оператор case
- •Область видимости идентификаторов
- •Пример записи
- •Оператор with
- •Массивы записей
- •Подпрограммы
- •Процедуры и функции
- •Объявление и определение подпрограммы
- •Параметры подпрограмм
- •Локальные процедуры и функции
- •Перегрузка подпрограмм
- •Параметры по умолчанию
- •Глава 3
- •Анатомия класса
- •Наследование
- •Ключевые слова is и as
- •Что такое класс?
- •Анатомия класса
- •Указатель Self
- •Пример класса
- •Анализ объявления и реализации
- •Наследование
- •Перекрытие методов
- •Ключевые слова is и as
Указатель Self
Новый термин. Все классы имеют скрытое поле с именем Self. Self – это указатель на «свой» экземпляр в памяти.
Поясним смысл Self на примере, показывающем как бы выглядело объявление класса TMyRect , если поле Self объявить явно:
TMyRect = class
private
Self : TMyRect;
Left : Integer;
Top : Integer;
Right : Integer;
Bottom : Integer;
Text : PChar;
public
function GetWidth : Integer;
function GetHeight : Integer;
procedure SetRect(ALeft, ATop, ARight, ABottom : Integer);
constructor Create;
constructor CreateVal(ALeft,ATop,ARight,ABottom : Integer);
destructor Destroy; override;
end;
Точно так компилятор и «видит» объявление любого класса. На самом деле компилятор сам добавляет поле Self к любому объекту. При создании объекта указатель Self инициализируется автоматически – в него заносится адрес структуры данных класса:
Rect := TMyRect.CreateVal(0, 0, 100, 100);
{ Теперь Rect и Rect.Self имеют одинаковые значения }
{ поскольку содержат один и тот же адрес памяти. }
Зачем же нам может понадобится поле Self? Вспомним, что каждый объект имеет собственную копию (экземпляр) полей в памяти. В то же время, все объекты одного и того же класса используют один и тот же исполняемый код методов. Иными словами, несколько экземпляров данных разделяют одни и те же методы. Компилятор всегда использует поле Self чтобы однозначно передать в метод те данные (т.е. – поля), которые принадлежат конкретному экземпляру класса – объекту. Рассмотрим, например такую версию описания метода GetWidth:
function TMyRect.GetWidth : Integer;
begin
Result := Right - Left;
end;
Именно так ее «видит» программист. Компилятор, однако интерпретирует этот текст по–своему, а именно:
function TMyRect.GetWidth : Integer;
begin
Result := Self.Right - Self.Left;
end;
С точки зрения действительности это не совсем точно, но вполне отражает предмет обсуждения. Этот код демонстрирует то, что на самом деле скрыто от программиста.
ПРЕДУПРЕЖДЕНИЕ: Никогда не изменяйте значение поля Self. Его можно использовать как указатель на объект класса в памяти или передавать в качестве фактического параметра другому объекту. Случайное (преднамеренное) изменение поля Self может привести к непредсказуемым последствиям. Это поле предназначено только для чтения.
Хотя Self – это «боец невидимого фронта», его можно эффективно использовать в программах. Например, рассмотрим как можно поместить на форму компонент во время выполнения программы, а не во время разработки. Этот пример иллюстрирует наиболее типичный случай использования указателя Self в программах Delphi.
Прежде всего отметим, что когда вы перетаскиваете компонент с палитры на форму, Delphi создает указатель на этот компонент и выполняет определенную работу, скрывая от программиста все ее детали. Если необходимо поместить копмонент на форму во время выполнения программы, руководство по VCL настоятельно требует отслеживания цепочки принадлежности. Иными словами, любой компонент должен «знать» своего «владельца» и «родителя семейства».
В рамках VCL владельцем (Owner) любой компоненты формы является форма. Но некоторая группа компонент, в свою очередь, может принадлежать и другому компоненту – элементу интерфейса Windows, который называется «родителем» (Parent).
Пусть, например, при нажатии одной кнопки на форму необходимо поместить новую кнопку. По правилам VCL надо указать форму –«владельца» новой кнопки и ее «родителя», которым может быть некий компонент – владелец группы элементов управления. В простейшем случае форма выступает и как владелец, и как «группирующий» компонент, т.е. является одновременно и «родителем».
Код обработчика соответствующего события мог бы иметь такой вид:
procedure TForm1.Button1Click(Sender: TObject);
var
Button : TButton;
begin
Button := TButton.Create(Self);
Button.Parent := Self;
Button.Left := 20;
Button.Top := 20;
Button.Caption := 'Click Me';
end;
В данном коде Self передается конструктору как фактический параметр (тем самым, свойство Owner новой кнопки будет указывать на форму, которой принадлежит кнопка). Далее свойству Parent созданной кнопки мы также присваиваем указатель на данную форму, поскольку другого группирующего компонента нет.
ПРИМЕЧАНИЕ: Выше было сказано, что классовые методы не имеют доступа к полям и методам класса. Это означает, что классовому методу ( в отличие от методов класса) недоступен указатель Self.
