- •Средства визуального программирования
- •090105 «Комплексное обеспечение информационной безопасности
- •Ставрополь, 2010 Содержание
- •Введение
- •Задачи дисциплины – дать основы:
- •В результате изучения дисциплины студенты должны
- •1.1. Версия 1
- •1.2. Версия 2
- •1.3. Версия 3
- •1.4. Версия 4
- •1.5. Версия 5
- •1.6. Версия 6
- •2.1. Главное окно
- •2.2. Окно формы
- •2.3. Окно дерева объектов
- •2.4. Окно инспектора объектов
- •2.5. Окно кода программы
- •3.1. Пустая форма и ее модификация
- •3.2. Размещение нового компонента
- •3.3. Реакция на события
- •3.4. Некоторые итоги
- •4.1. Страница standard
- •4.2. Страница additional
- •4.3. Страница win32
- •4.4. Страница system
- •4.5. Страница dialogs
- •4.6. Страница win31
- •4.7. Страница samples
- •4.8. Компоненты для работы с базами данных
- •4.9. Компоненты для доступа к интернет
- •4.10. Доступ к серверам автоматизации
- •5.1. Учебная программа
- •5.2. Структура программ delphi
- •5.3. Типы
- •5.4. Операторы языка
- •5.5. Массивы
- •5.6. Процедуры и функции
- •6.1. Алфавит
- •6.2. Идентификаторы
- •6.3. Константы
- •6.4. Выражения
- •6.5. Операции
- •7.1. Простые типы
- •7.2. Структурированные типы
- •7.3. Строки
- •7.4. Указатели и динамическая память
- •7.5. Псевдонимы типов
- •8.1. Локализация имен
- •8.2. Описание подпрограммы
- •8.3. Параметры-массивы и параметры-строки
- •8.4. Процедурные типы
- •8.5. Рекурсия и опережающее описание
- •9.1. Основные понятия
- •9.2. Составляющие класса
- •9.3. Объявление класса
- •9.4. Интерфейсы
- •10.1. Основные свойства варианта
- •10.2. Преобразование вариантов к данным других типов
- •10.3. Подпрограммы для работы с вариантами
- •10.4. Вариантные массивы
- •10.5. Пользовательские варианты
- •11.1. Доступ к файлам
- •11.2. Процедуры и функции для работы с файлами
- •11.3. Текстовые файлы
- •11.4. Типизированные файлы
- •11.5. Нетипизированные файлы
- •11.6. Средства windows для работы с файлами
- •11.7. Отображение файлов в память
- •11.7.1. Создание/открытие файла
- •11.8. Объектная модель работы с файлами
- •12.1. Структура модулей
- •12.2. Заголовок модуля и связь модулей друг с другом
- •12.3. Интерфейсная часть
- •12.4. Исполняемая часть
- •12.5. Инициирующая и завершающая части
- •12.6. Доступ к объявленным в модуле объектам
- •12.7. Типы модулей в delphi
- •13.1. Назначение
- •13.2. Реализация
- •13.3. Пример
- •13.4. Использование
- •13.5. Включение в библиотеку форм
- •15.1. Константы простых типов и типа string
- •15.2. Константы-массивы
- •15.3. Константы-записи
- •15.4. Константы-множества
- •15.5. Константы-указатели
- •15.6. Инициация переменных
- •16.1. Класс exception - обработка исключений
- •16.2. Класс tlist - списки
- •16.3. Классы tstrings и tstringlist -наборы строк и объектов
- •16.4. Графический инструментарий
- •Список используемой литературы
9.2. Составляющие класса
9.2.1. Поля
Полями называются инкапсулированные в классе данные. Поля могут быть любого типа, в том числе - классами, например:
type TMyClass = class
aIntField: Integer;
aStrField: String;
aObjField: TObject;
end;
Каждый объект получает уникальный набор полей, но общий для всех объектов данного класса набор методов и свойств. Фундаментальный принцип инкапсуляции требует обращаться к полям только с помощью методов и свойств класса. Однако в Object Pascal разрешается обращаться к полям и напрямую:
type
TMyClass = class
FIntField: Integer;
FStrField: String; end;
var
aObject: TMyClass;
begin
aObject.FIntField := 0;
aObject.FStrField := 'Строка символов';
end;
Класс-потомок получает все поля всех своих предков и может дополнять их своими, но он не может переопределять их или удалять.
Таким образом, чем ниже в дереве иерархии располагается класс, тем больше данных получают в свое распоряжение его объекты.
9.2.2. Методы
Инкапсулированные в классе процедуры и функции называются методами. Они объявляются так же, как и обычные подпрограммы:
type
TMyClass = class
Function MyFunc(aPar: Integer): Integer;
Procedure MyProc;
end;
Доступ к методам класса, как и к его полям, возможен с помощью составных имен:
var
aObject: TMyClass;
begin
aObject.MyProc;
end;
Как уже говорилось, методы класса могут перекрываться в потомках. Например:
type
TParentClass = class Procedure DoWork;
end;
TChildClass = class(TParentClass) Procedure DoWork;
end;
Потомки обоих классов могут выполнять сходную по названию процедуру DoWork, но, в общем случае, будут это делать по-разному. Такое замещение методов называется статическим, т. к. реализуется компилятором.
В Object Pascal гораздо чаще используется динамическое замещение методов на этапе прогона программы. Для реализации этого метод, замещаемый в родительском классе, должен объявляться как динамический (с директивой dynamic) или виртуальный (virtual). Встретив такое объявление, компилятор создаст две таблицы -DMT (Dynamic Method Table) и VMT (Virtual Method Table) и поместит в них адреса точек входа соответственно динамических и виртуальных методов. При каждом обращении к замещаемому методу компилятор вставляет код, позволяющий извлечь адрес точки входа в подпрограмму из той или иной таблицы. В классе-потомке замещающий метод объявляется с директивой override (перекрыть). Получив это указание, компилятор создаст код, который на этапе прогона программы поместит в родительскую таблицу точку входа метода класса-потомка, что позволит родителю выполнить нужное действие с помощью нового метода.
Пусть, например, родительский класс с помощью методов show и Hide соответственно показывает что-то на экране или прячет изображение. Для создания изображения он использует метод Draw с логическим параметром:
type
TVisualObject = class(TWinControl)
Procedure Hide;
Procedure Show;
Procedure Draw(IsShow: Boolean); virtual;
end;
TVisualChildObject = class(TVisualObject)
Procedure Draw(IsShow: Boolean); override;
end;
Реализация методов show и Hide очень проста:
Procedure TVisualObject.Show;
begin
Draw(True) ;
end;
Procedure TVisualObject.Hide;
begin
Draw(False) ;
end;
Методы Draw у родителя и потомка имеют разную реализацию и создают разные изображения. В результате родительские методы show и Hide - прятать или показывать те или иные изображения будут в зависимости от конкретной реализации метода Draw у-любого из своих потомков. Динамическое связывание в полной мере реализует полиморфизм классов.
Разница между динамическими и виртуальными методами состоит в том, что таблица динамических методов DMT содержит адреса только -тех методов, которые объявлены как dynamic в данном классе, в то время как таблица VMT содержит адреса виртуальных методов не только данного класса, но и всех его родителей. Значительно большая по размеру таблица VMT обеспечивает более быстрый поиск, в то время как при обращении к динамическому методу программа сначала просматривает таблицу DMT у объекта, затем -у его родительского класса и так далее, пока не будет найдена нужная точка входа.
Динамически перекрываемые методы часто могут вообще ничего не делать. Такие методы называются абстрактными, они обязаны перекрываться в потомках. Программист может запретить вызов абстрактного метода, объявив его с директивой abstract. Например:
type
TVisualObject = class(TWinControl)
Procedure Draw(IsShow: Boolean); virtual; abstract;
end;
TVisualChildObject = class(TWinControl)
Procedure Draw(IsShow: Boolean); override; end;
var
aVisualObject: TVisualObject;
aVisualChild: TVisualChildObject ;
begin
aVisualObject.Show; {Ошибка/ Обращение к абстрактному методу} aVisualChild.Show; {Нормальное обращение. Метод Draw у класса TVisualChildObject перекрыт.)
end;
Обращение к неперекрытому абстрактному методу вызывает ошибку периода исполнения. Разумеется, в грамотно составленной программе абстрактные методы никогда не вызываются. Классы, содержащие абстрактные методы, называются абстрактными. Такие классы инкапсулируют общие свойства своих неабстрактных потомков, но объекты абстрактных классов никогда не создаются и не используются. Для эксплуатации абстрактных классов в библиотеку классов Delphi включаются классы-потомки, в которых перекрываются абстрактные методы родителя.
В состав любого класса входят два специальных метода -конструктор и деструктор. У класса TObject эти методы называются create и Destroy, так же они называются в подавляющем большинстве его потомков. Конструктор распределяет объект в динамической памяти и помещает адрес этой памяти в переменную self, которая автоматически объявляется в классе. Деструктор удаляет объект из кучи. Обращение к конструктору должно предварять любое обращение к полям и некоторым методам объекта. По своей форме конструкторы и деструкторы являются процедурами, но объявляются с помощью зарезервированных слов constructor и Destructor:
type
TMyClass = class IntField: Integer; Constructor Create(Value: Integer);
Destructor Destroy;
end;
Любые поля объекта, а также методы класса, оперирующие с его полями, могут вызываться только после создания объекта с помощью вызова конструктора, т. к. конструкторы распределяют объект в динамической памяти и делают действительным содержащийся в объекте указатель.
var
MyObject: TMyClass;
begin
MyObject.IntField := 0;
{ Ошибка! Объект не созданконструктором!}
MyObject := TMyClass.Create;
// Надо так: создаем объект
MyObject.IntField := 0;
// и обращаемся к его полю
MyObect.Free;
// Уничтожаем ненужный объект
end;
В базовом классе TObject определен метод Free, который сначала проверяет действительность адреса объекта и лишь затем вызывает деструктор Destroy. Обращение к деструктору объекта будет ошибочным, если объект не создан конструктором, поэтому для уничтожения ненужного объекта следует вызывать метод Free, как это сделано в предыдущем примере.
Большинство конструкторов реализуют некоторые действия, необходимые для правильной работы объекта. Поэтому в конструкторе класса-потомка следует сначала вызвать конструктор своего родителя, а уже затем осуществлять дополнительные действия. Вызов любого метода родительского класса достигается с помощью зарезервированного слова inherited (унаследованный):
Constructor TMyClass.Create(Value: Integer);
// Возможная реализация конструктора
begin
Inherited Create; // Вызываем унаследованный конструктор IntField := Value; // Реализуем дополнительные действия
end;
Некоторые методы могут вызываться без создания и инициации объекта. Такие методы называются методами класса, они объявляются с помощью зарезервированного слова class:
type
TMyClass = class(TObject)
class Function GetClassName: String;
end;
var
S: String;
begin
S := TMyClass.GetClassName;
end;
Методы класса не должны обращаться к полям, т. к. в общем случае вызываются без создания объекта, а следовательно, в момент вызова полей просто не существует. Обычно они возвращают служебную информацию о классе - имя класса, имя его родительского класса, адрес метода и т. п.
9.2.3. Одноименные методы
В отличие от остальных версий Delphi в версиях 4...6 появилась возможность в рамках одного класса иметь несколько одноименных методов. Описанный выше механизм перекрытия родительского метода одноименным методом потомка приводит к тому, что потомок “не видит” перекрытый родительский метод и может обращаться к нему лишь с помощью зарезервированного слова inherited. В Delphi 4 введено зарезервированное слово overload (перезагрузить), с помощью которого становятся видны одноименные методы как родителя, так и потомка.
При обнаружении одноименного метода компилятор Delphi предупреждает о том, что у класса уже есть аналогичный метод с дру
гими параметрами. Для подавления сообщений объявление одноименного метода можно сопровождать зарезервированным словом reintrpduce (вновь ввести).
Ч тобы одноименные методы можно было отличить друг от друга,каждый из них должен иметь уникальный набор, параметров. В ходе шлпоянения программы при: обращении к одному, из одноименнх
методов программа проверяет; тип и количество фактических параметров обращения и выбирает нужный метод
В следующем примере в классе TForm1 используются целых 4 одноименных метода close. Лишь один из них - унаследованный метод без параметра выполняет свои основные функции - закрывает окно. Три других отличаются набором параметров и выводят сообщение в заголовок окна.
Поместите на пустую форму четыре кнопки TButton и напишите такие обработчики их событий OnClick:
procedure TForm1.ButtonlClick(Sender: TObject);
begin
Close('Строка символов')
end;
procedure TFormi.Button2Click(Sender: TObject);
begin
Close(123)
end;
procedure TFormi.ButtonSClick(Sender: TObject);
begin
Close (20,300) ;
end;
procedure TFormi.Button4Click(Sender: TObject);
begin
Close end;
Теперь в раздел private класса Tform1 вставьте три таких объявления методов close:
private
{ Private declarations }
procedure Close(S: String);
reintroduce;
overload;
procedure Close(I: Integer);
reintroduce;
overload;
procedure Close(I,J: Integer);
reintroduce;
overload;
И, наконец, в разделе implementation поместите описания объявленных методов:
procedure TForm1.Close(S: String) ;
begin
Caption := S end;
procedure TFormI.Close(I: Integer);
begin
Caption := IntToStr(I) end;
procedure TFormI.close(I,J: Integers);
begin
Caption := IntToStr(i*j)
end;
Теперь после запуска программы три первые кнопки будут вызывать методы close класса Tform1 и менять заголовок окна, в то время как кнопка Button4 обратится к методу close родительского класса т Form и закроет окно.
9.2.4. Свойства
Свойства - это специальный механизм классов, регулирующий доступ к полям. Свойства объявляются с помощью зарезервированных СЛОВ property, read И write (слова read И write считаются зарезервированньши только в контексте объявления свойства). Обычно свойство связано с некоторым полем и указывает те методы класса, которые должны использоваться при записи в это поле или при чтении из него. Например:
type
TaClass = class
IntField: Integer; Function GetField: Integer;
Procedure SetField (Value: Integers);
Property IntegerValue: Integer read GetField
write SetField;
end;
В контексте программы свойство ведет себя как обычное поле. Например, мы могли бы написать такие операторы:
var
aClass: TaClass;
Value: Integer;
begin
aClass := TaClass.Create; { Обязательное обращение к
конструктору перед обращением к полю или свойству!} aClass.IntegerValue := 0;
Value := aClass.IntegerValue;
aClass.Destroy; // Удаление ненужного объекта
end;
Более того, возможен и такой оператор присваивания:
aClass.IntField := NewValue;
Разница между этим оператором и оператором
aClass.IntegerValue := NewValue;
заключается в том, что при обращении к свойству автоматически подключается метод setFieid, в котором могут реализовываться специфичные действия. Вспомним использовавшийся нами в учебной программе оператор
IbOutput.Caption := 'Строка';
Свойство Caption компонента Label вызывает метод setText, который не только запоминает строку символов во внутренней переменной, но и осуществляет прорисовку метки с новым текстом.
Если нет необходимости в специальных действиях при чтении или записи свойства, вместо имени соответствующего метода можно указывать имя поля:
type
TaClass = class IntFiled: Integer;
Procedure SetFieid (Value: Integers;
Property IntegerValue:
Integer read IntFiled write SetFieid;
end;
Если необходимо, чтобы свойство было доступно только для чтения или только для записи, следует опустить соответственно часть write или read. Вообще говоря, свойство может и не связываться с
полем. Фактически оно описывает один или два метода, которые осуществляют некоторые действия над данными того же типа, что и свойство.