Основы объектно-ориентированного программирования
Классы
Поля
Свойства
События
Методы
Информация о типе во времени выполнения
В этой главе мы кратко рассмотрим основы объектно-ориентированного программирования.
Изучим такие понятия, как инкапсуляция, наследование м полиморфизм. Рассмотрим
классы, поля, свойства, события, методы объектов. В заключение мы узнаем, что
такое типы времени выполнения (RTTI).
Основы объектно-ориентированного программирования
Язык Object Pascal является объектно-ориентированным языком. Таким образом,
готовое приложение, написанное на данном языке, будет иметь в своем составе
объекты.
Итак, рассмотрим, что такое класс. Класс - это тип данных, который включает
в себя какие-либо данные и операции над ними.
Объект - это экземпляр какого-либо класса.
Таким образом, класс - это описание (тип), а объект - это то, что создано в
соответствии с этим описанием. Например, все вы хорошо представляете, что такое
стол. Стол - это нечто, имеющее столешницу и четыре ножки. Такое вот описание
стола и будет классом, а конкретный экземпляр стола, за которым вы сейчас сидите,
читая эту книгу, является объектом данного класса.
До создания объектно-ориентированных языков программирования данные и операции
над данными рассматривали как отдельные элементы. Что такое объект, достаточно
просто можно понять, если вспомнить работу с записями. Записи состоят из областей,
которые содержат данные разных типов (каждая область записи имеет собственный
тип данных).
Объекты - это тоже хранилища разных типов данных. Данные объекта называются
полем (field) и аналогичны полям записи. Но объекты, в отличие от записей, содержат
еще процедуры и функции, которые применимы к полям данного объекта. Эти процедуры
и функции называются методами (methods). Изменять поля объекта можно при помощи
свойств (properties) объекта. Каждое свойство объекта в Kylix представляет собой
поле и методы (так называемые методы доступа), которые позволяют считывать значение
поля и задавать его. Свойства можно изменять в процессе разрзй5от!ййупри-жения
с помощью инспектора объектов.
Примечание
Информацию о работе с инспектором объектов Kylix, а также другими окнами вы
найдете во второй части этой книги.
К основным принципам объектно-ориентированного программирования отсятся:
инкапсуляция;
наследование;
полиморфизм.
Инкапсуляция - это объединение данных и обрабатывающих их методов утри одного
класса.
Наследование обозначает, что объекты могут получать свои свойства и методы других
объектов (которые называют в данном случае предками). Объекты-наследннки берут
от предков все свойства, методы и поля. Эти свойства, методы и поля в объекте-наследнике
могут сохраняться либо в неизменном виде либо в измененном. Кроме того, объекты-наследники
могут иметь в своем составе дополнительно новые поля, методы или свойства.
Полиморфизм подразумевает, что методы различных объектов могут иметь знаковые
имена, но отличаться по своему содержанию. Это получается в реультате переопределения
метода объекта-предка в объекте-наследнике. При этом обращение к одному и тому
же методу у объекта-предка и объекта-потомка может привести к разным результатам.
Классы
Классы - это специальные типы данных языка Object Pascal, которые используются
для описания объектов.
В состав класса входят поля, свойства и методы. Подробное их описание смотрите
далее в этой главе.
Типичное определение нового класса выглядит следующим образом:
typе Имя класса = class (Класс-предок)
{Список состава класса}
private
{частые описания}
protected
{защищенные описания}
public
{общедоступные описания}
published
{опубликованные описания}
end;
где Имя класса - любое корректное ИМЯ (выбирается ПРОИЗВОЛЬНО), Класс-предок
- название класса, наследником которого является создаваемый класс, а список
состава класса содержит свойства и методы нового класса.
Для каждого элемента класса можно установить разную видимость. Для этого предназначены
четыре ключевых слова: private, protected, public и published.
Видимость элемента класса определяет, где в программе и как будет виден данный
элемент класса. Минимальная видимость элемента класса задается ключевым словом
private, ключевое слово protected определяет средний уровень видимости. Наконец,
public и published определяют наивысшую степень доступности.
Если перед описанием элемента класса не ставится ключевое слово, определяющее
его степень видимости, то считается, что видимость элемента такая же, как и
у предыдущего элемента класса.
Рассмотрим все четыре ключевых слова более подробно.
Private (частные) - определяет элементы класса, которые не видны вне модуля,
в котором был объявлен класс, содержащий эти элементы. Другими словами, частные
методы не могут быть вызваны из других модулей, а частные поля или свойства
не могут быть считаны или изменены из других модулей.
Protected (защищенные) - определяет элементы класса, которые видны только внутри
модуля, где определен класс, содержащий эти элементы, а также внутри других
модулей, где присутствуют классы-потомки данного класса.
Public (общедоступные) - определяет элементы класса, которые видны в любом месте
программы и из любых модулей, в которых виден сам класс.
Published (опубликованные) - определяет элементы класса, имеющие ту же видимость,
что и public-элементы. Единственное отличие заключается в том, что опубликованные
элементы порождают информацию о типе времени выполнения (RTTI). Благодаря данной
информации. Kylix может осуществить проверку принадлежности элементов объекта
к тому или иному классу. Kylix использует RTTI для доступа к значениям свойств
при сохранении и загрузке файлов форм, чтобы иметь возможность отобразить свойства
в инспекторе объектов и ассоциировать конкретные методы с конкретными свойствами.
Все методы классов могут быть опубликованы, за исключением перегруженных (overload)
методов, имеющих одинаковые имена.
Перегруженными называются методы, которые имеют одинаковые имена, но спользуют
в качестве параметров данные различных типов. В процессе вызова такого метода
компилятор решает сам, какой из методов вызвать в за-исимости от аргументов,
передаваемых при вызове метода.
В Kylix имеется понятие абстрактного класса.
Абстрактный класс описывает несуществующий объект. Он нужен для того, гобы описать
некоторые фундаментальные свойства и методы объектов, оторые будут созданы из
абстрактного класса.
Все объекты в Kylix созданы из абстрактного класса TObject. Класс TObject -
редок многих простых классов. Этот класс объединяет в себе основные ункции,
которые свойственны всем объектам Kylix. TObject обеспечивает:
возможность создания, уничтожения и управления экземплярами объек-тоё, а также
резервирование памяти и ее освобождение после уничтожения экземпляра;
поддержку информации об объектах и типах;
поддержку обработки сообщений.
Итак, все классы в Kylix - потомки класса TObject.
Класс называется прямым потомком класса тоь TObject, если он произведен непосредственно
от класса TObject.
Класс называется косвенным потомком от тсласса TObject, если он произведен от
класса, являющегося прямым или косвенным потомком класса TObject (то есть произведен
от промежуточного класса).
Примечание
В другой литературе можно встретить названия дочерний класс и класс-потомок.
Дочерний класс - это прямой потомок, а класс-потомок - это косвенный потомок
в терминологии данной книги.
Если при создании нового класса не указывается родительский класс, то считается,
что родитель - класс TObject.
Поля
we объекта предназначено для хранения данных, содержащихся в объекте, шсание
поля не отличается от описания обычной переменной и может быть любого типа.
Приведем пример описания поля объекта:
typе TNumber = class
FInt; Integer;
end;
Данный пример создает в классе TNumber новое поле Fint целочисленного типа.
Примечание
По взаимному соглашению разработчиков, имена полей должны начинаться с буквы
F (по-английски field означает поле).
Обратите внимание на то, что данный класс TNumber является прямым потомком класса
TObject. Так как после слова class в круглых скобках не указывается класс-предок.
Поэтому объявление типа в первой строке примера может быть таким:
type TNumber = class (TObject)
После создания нового класса он наследует все поля своего класса-предка. Удалить
или переопределить поля класса-предка невозможно.
Свойства
Свойства так же, как и поля, определяют атрибуты объекта. Но в отличие от полей
свойства реализуют механизм доступа для чтения или изменения данных в полях
объекта.
Вернувшись к примеру со столом, можно сделать следующее сравнение: поле "количество
ножек" объекта "стол" будет хранить целое число, обозначающее
количество ножек, а свойство "ножки" объекта "стол"может
изменять это значение. С помощью данного'свойства можно задать "количество
ножек" равным трем, четырем и т. д.
Свойства позволяют изменять атрибуты объекта, в том числе, и вычисляемыми значениями.
Объявление свойства объекта должно содержать его имя и тип, а также, как минимум,
одно объявление способа доступа к данному свойству (описания). Синтаксис объявления
свойства объекта имеет вид:
property Имя свойства: тип описания;
Имя свойства должно быть уникальным;
тип - определяет, значения какого типа могут быть записаны в данном свойстве;
описания - объявления способов доступа к данному свойству.
Каждое свойство объекта должно иметь, как минимум, одно обязательное объявление
способа доступа к свойству. Имеется два обязательных описания доступа к свойству
объекта: чтение (read) значения свойства и запись (write) значения свойства.
Синтаксис обязательных описаний read и write имеет следующий вид:
read поле ИЛИ метод
write поле ИЛИ метод
где поле или метод - поле, из которого берется или в которое помещается значение
свойства, или метод, который берет или помещает значение свойства компонента.
Несложно догадаться, что объявление read (читать) описывает поле или меттод
предназначенные для чтения значения свойства, а объявление write (писать) описывает
поле или метод, предназначенные для записи значения свойства компонента.
В листинге 5.1 приведен пример описания свойств объекта.
Листинг 5.1 Описание свойств объекта
typе TMyObject = class // Объявление нового класса
private
FInt: integer; // Объявление целочисленного поля
FReal: real; // Объявление вещественного поля
FChar: char; // Объявление поля символьного типа
published
property Prop1: integer read FInt write FInt; // Объявление
// свойства Prop1, с помощью которого можно читать значение поля
// FInt и записывать данные в это же поле
property Prop2: real read FReal;. // Свойство Ргор2 предназначено
// только для чтения значения поля FReal
property РгорЗ: char write FChar; // Свойство РгорЗ предназначено
// только для записи данных в поле FChar
end;
После такого объявления программист получает доступ к полям объекта через три
свойстваа Prop1, Prop2 и РгорЗ.
События
Событие (event) - это механизм, который связывает какое-либо происшест-с конкретным
кодом, называемым обработчиком события (event handler).
Механизм обработки событий будет подробно рассмотрен во второй части книги.
Пока лишь отметим, что среда Kylix поддерживает два основных типа событий:
пользовательские (widget);
системные (system).
К пользовательским относят события, которые происходят из-за взаимодействия
пользователя с программой. Например, движение мышкой, нажатие кнопки и т. д.
Системные события - это события, происходящие в операционной системе. Например,
тикание системного таймера.
Методы
Методы- это процедуры или функции, принадлежащие объекту. Методы .определяют
поведение объекта. Для вызова метода объекта нужно указать имя объекта, с которым
ассоциирован данный метод, затем, через точку, - название метода. Например:
MyObject.Method1;
Вызывается метод Methodi объекта MyObject.
Для создания метода его нужно сначала объявить внутри описания класса или компонента,
содержащего данный метод. Например:
type
TMyObject = class(TObject)
procedure DoSomething; // Объявление метода DoSomething
end;
Здесь, внутри описания нового класса, объявляем метод DoSomething с помощью
служебного слова procedure. Эта процедура может находиться где угодно внутри
модуля, в котором был описан данный класс. Например:
procedure TMyComponent.DoSomething;
begin
// Здесь размещаем команды и операторы, которые должны выполняться
// при вызове метода DoSomething на выполнение
end;
Заметим, что при создании процедуры DoSomething мы должны указывать ее полное
имя, вместе с указанием имени компонента или класса (procedure TMyComponent.DoSomething;).
В зависимости от вида метода, он может вызываться различными способами. Методы
бывают следующих видов:
статические;
виртуальные (virtual);
динамические (dynamic);
перегруженные (override);
методы обработки сообщений (message);
абстрактные (abstract).
После заголовка метода в описании класса через точку с запятой указывается дин
из вышеперечисленных идентификаторов (virtual, ..., abstract).
По умолчанию методы являются статическими и вызываются как любые ругие подпрограммы.
Более подробно о методах мы расскажем в пятой части книги, где речь пойдет о
создании собственных компонентов и пакетов компонентов.
Информация о типе во времени выполнения
Иформация о типе во время выполнения (Runtime Type Information, RTTI) - это
способность среды Kylix предоставлять приложению информацию об объектах во время
выполнения приложения. Так как все объекты Kylix являются потомками класса TObject,
то все они содержат указатель на информацию о типе, а также методы для работы
с этой информацией. В приведенной ниже табл. 5.1 рассмотрены некоторые из этих
методов.
Таблица 5.1. Методы для работы с RTTI
Название метода | Тип возвращаемого результата | Результат |
Classlnfo | Pointer | Указатель на информацию о объекта типе |
ClassName | String | Имя класса объекта |
ClassParent | Tclass | Тип класса-предка объекта |
ClassType | Tclass | Тип объекта |
InheritsFrom | Boolean | Является ли объект потомком данного класса |
InstanceSize | Word | Размер объекта как экземпляра класса в байтах |
ыДля работы с информацией о типе времени исполнения в Kylix имеется два новных
оператора: is и as.
Синтаксис использования оператора is:
Объект is Класс;
Данный оператор применяется для проверки того, принадлежит ли объект к званному
классу. В том случае, если объект принадлежит классу, возвращается значение
True, в противном случае возвращается False.
Приведем пример использования оператора is.
if ActiveControl is TEdit then TEdit (ActiveControl) . SelectAll;
В этом примере производится проверка, имеет ли активный компонент тип TEdit.
И если это так, то в нем выделяется весь имеющийся текст.
Примечание
Для более глубокого понимания компонентов и их свойств обратитесь ко второй
части книги.
Синтаксис использования оператора as:
Объект as Класс;
Данный оператор служит для приведения одного типа к другому.
Информация о типе времени выполнения используется в Kylix в основном для определения,
с объектом какого типа сейчас работает приложение.