- •Объектно-ориентированное программирование
- •Часть 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;
|
ЭЛЕКТРОСТАЛЬСКИЙ ПОЛИТЕХНИЧЕСКИЙ ИНСТИТУТ (филиал) Федерального государственного образовательного учреждения высшего профессионального образования «Государственный технологический университет «Московский институт стали и сплавов» |
Объектно-ориентированное программирование
Часть 1 классы и объекты
УЧЕБНОЕ ПОСОБИЕ по курсу
"Прикладное программирование"
Введение
Object-Oriented Programming (Объектно-ориентированное программирование - ООП) стало естественным способом разработки сложного программного обеспечения с графическим интерфейсом пользователя. Оно основано на объектно-ориентированной модели, для которой объекты являются основным предметом рассмотрения. Эта модель включает описание объектов и средства их взаимодействия друг с другом. Объектно-ориентированный подход при разработке программного обеспечения уже продемонстрировал свои возможности в создании систем в самых разных областях любого размера и сложности.
Объект (Object) - это переменная структурированного типа данных, включающая, как элементы данных, так и операции с этими элементами, упакованными вместе для удобства использования. Объединение данных и кода в одну конструкцию называется инкапсуляцией (encapsulation). Важно подчеркнуть, что операции и данные, которыми они оперируют, тесно связаны друг с другом. Простое включение операций и данных в одну структуру возможно и в паскалевской записи.
Каждый объект является экземпляром (instance) определенного класса. Во время выполнения программы объекты взаимодействуют друг с другом, вызывая методы-операции, являющиеся подпрограммами, характерными для определенного класса.
Класс (Class) - это структурированный тип данных или объединяющая концепция (абстракция) набора объектов (экземпляров), имеющих общие характеристики. Класс определяет семантику - общий интерфейс с окружающим миром, посредством которого можно взаимодействовать с отдельными объектами. Все представители (экземпляры) одного класса аналогичны друг другу, поскольку они имеют одинаковый интерфейс.
Классы могут быть связаны друг с другом отношениями наследования (inheritance), с их помощью количество элементов данных и/или операций с ними может увеличиваться, а описания существующих классов многократно использоваться при описании новых. Наследование является одним из механизмов, посредством которого объекты одного класса могут включаться в работу объектов другого класса. Наследование предоставляет мощный механизм моделирования отношений, существующих в реальном мире.
При определенных обстоятельствах объекты могут вызывать методы-операции не только их непосредственного класса, но и любого из классов-предков, таким образом поддерживается полиморфизм (polymorphism). Полиморфизм - это, в переводе с греческого, много форм. Применительно к ООП это означает, что может существовать несколько версий какого-то метода и один и тот же вызов этого метода может использовать различные его версии.
1. Классы и объекты
Данные в объекте определяются и выглядят подобно полям записи (Record) в Паскале, но без вариантной части. Могут быть объявлены поля различных типов, которым при создании объекта или в процессе работы программы присваиваются конкретные значения. Комбинация значений всех полей объекта определяет состояние этого объекта. Изменение значения поля изменяет и состояние объекта. Поэтому значения полей уникальны для каждого экземпляра класса (объекта), хотя и может быть несколько объектов с полностью идентичными значениями полей.
Объявляются поля данных внутри описания класса способом, аналогичным определению полей записей и похожим на объявление обычных переменных. Можно перечислить одно или более имен полей одного типа, разделенных запятыми, а затем указать наименование типа, отделив его двоеточием. Заканчивается каждое описание точкой с запятой после названия типа.
Как источник действий, объект использует набор методов, т.е. подпрограмм, разработанных для операций с полями. Все методы совместно определяют поведение объекта. Активирование метода объекта проявляется в действии, совершаемом объектом. Адреса вызова некоторых методов объекта определяются на этапе компиляции программы, а других - с помощью специальной таблицы, создаваемой после инициализации программы. Каждый объект содержит указатель на такую специальную таблицу, содержащую информацию, необходимую для вызова метода. Эта таблица является принадлежностью класса и для нее выделяется память. Таким образом, методы у объектов одного класса общие.
Классическое правило ООП утверждает, что для обеспечения надежности нежелателен прямой доступ к полям объекта: чтение и изменение их содержимого должно производиться посредством вызова соответствующих методов. В объектах Delphi пользователь может быть полностью отгорожен от полей с помощью свойств, в то время как поля у записи не защищены и доступны для возможного неверного использования.
Таким образом, класс - это структурированный тип данных языка Object Pascal (OP). Класс представляет собой описание того, как будет выглядеть и вести себя его представитель (экземпляр или объект).
Во многих объектно-ориентированных языках объявление переменной, имеющей тип класса, автоматически создает объект. В OP вместо этого используется ссылочная модель объектов (object reference model), т.е. каждая переменная типа класса содержит не значение объекта, а лишь ссылку (указатель) на область памяти, в которой содержится объект, т.е. переменная типа класс - это просто ссылка на экземпляр. Таким образом, в OP все экземпляры или объекты могут быть только динамическими, поэтому отпала необходимость в использовании непременного атрибута указателя '^' - caret.
Для того чтобы использовать новый тип данных в программе, необходимо как минимум объявить переменную этого типа. За выделение памяти, т.е. за создание новых своих экземпляров-объектов отвечает класс с помощью метода, называемого конструктором. Поскольку, как известно, выделение памяти для динамических переменных происходит только во время выполнения программы, то фактически объекты вызываются к жизни во время исполнения. Статически во время трансляции программы выделяется память только под объектную ссылку, размер которой существенно меньше, чем необходимо для хранения экземпляра класса, поскольку память для полей не выделяется.
Отметим, что, объявляя в программе переменную того или иного класса, мы фактически при работе программы лишь создадим структуру, включающую только поля, а методы у всех экземпляров одного класса размещены в одном месте - в описании класса. Доступ к ним осуществляется через указатель на класс, имеющийся у каждого экземпляра.
Таким образом, класс это не просто описание структурированного типа данных, а активная структура, существующая в программе и способная выполнять определенные действия по созданию экземпляров класса. Создание, т.е. определение адреса и выделение памяти, а также инициализация экземпляров класса (объектов) осуществляется с помощью класса.
Однако класс не уничтожает экземпляры, поскольку эту способность поддерживает сам активный экземпляр, т.е. экземпляры самоуничтожаются при вызове соответствующего метода, называемого деструктором.
а) Объявление класса, т.е. объявление типа данных, определяет состав полей данных экземпляров класса и набор допустимых операций над ними, и его синтаксис следующий:
Type <имя класса>=Сlass[(<имя родительского класса>)}
Определение класса> // Определение полей, свойств и методов
End;
Примечания:
• Классы могут быть объявлены либо в секции интерфейса модуля, либо на верхнем уровне вложенности секции реализации. Таким образом, не допускается описание класса внутри процедур и функций и других блоков кода. Они могут быть только глобальными типами.
• Возможно предварительное объявление класса, но без использования директивы Forward'.
Type <имя класса>=Сlass[(<имя родительского класса>)};
• В OP у всех классов есть общий класс-прародитель TObject. При создании пользовательского класса непосредственно от TObject имя родительского класса можно не указывать.
• Определение класса может быть разделено на несколько разделов с разной степенью видимости (доступности) их компонентов. Каждый раздел может начинаться с одного из ключевых слов-директив: Private, Protected, Public, Published (если компилировался с директивой SM+). По умолчанию, если нет ни одного слова-директивы или до первой директивы. определяющим разделом является Public.
• Объявление класса включает три основных группы компонентов объектов, называемых интерфейсом класса:
• данные объекта или атрибуты исходных данных, называемые чаще всего полями;
' методы объекта или операции над данными;
• свойства объекта - это высокоуровневые атрибуты данных, которые тесно связаны с соответствующими методами доступа к данным.
• Объявление полей в каждом из четырех разделов объявления класса должно предшествовать объявлению методов и свойств.
• Имена классов принято начинать с буквы Т, а имена полей с буквы F.
• По существу имеется два вида полей внутри экземпляра класса: поля прямого доступа и косвенного доступа:
• поле прямого доступа - это реальная часть данных, непосредственно встроенная в экземпляр класса. Примером может служить целое число или строка. Прямой доступ требует ресурса памяти для хранения каждого экземпляра класса, в точности равного объявленному размеру, поэтому значения этих полей могут храниться внутри каждого экземпляра класса. Выделение памяти под строки Delphi делает динамически и автоматически:
• поле косвенного доступа - это ссылка на некоторый другой объект, обычно на экземпляр другого класса. Поле косвенного доступа требует сравнительно немного памяти для хранения ссылки, поскольку в этом поле хранится адрес - 4 байта.
• Объект может содержать (включать) другой объект, т.е. владеть им. В этом случае объект-хозяин ответственен как за создание экземпляра этого объекта (выделение памяти соответствующим конструктором, когда это необходимо), так и за уничтожение (соответствующим деструктором, когда он больше не требуется). Например, экранная форма владеет всеми объектами, на ней расположенными: кнопками, полями редактирования и т.п.
• Объект может быть ассоциирован с другим объектом. В этом случае объекты "знают " друг о друге, могут вызывать методы друг друга и ссылаться, но они не отвечают за создание и уничтожение друг друга. Например, совокупность компонентов для работы с базами данных, организации DDE-связи и т.п.
б) Создание экземпляра класса. Для создания экземпляра необходимо объявить переменную в секции Var, а затем отвести ей память в куче соответствующим конструктором.
в) Обращение к полям экземпляра класса. Можно обращаться к полям данных следующим образом:
• используя точечную нотацию (или полное имя):
<имя объекта>.<имя поля>:=<значение>;
• используя оператор With, как при обращении к полям записи в Паскале:
With <имя объекта> Do Begin
<имя поля ]>:=<значение1>;
<имя поля 2>:=<значение2>;
. . .
End;
Рассмотрим пример объявления, создания и использования объекта.
• Объявим класс TLine:
Type TLine=Class
X, Y, Length, Angle: Integer; // Поля класса
Constructor Create; // Конструктор класса
Procedure MoveTo(NewX, NewY: Integer); // 1-й метод класса
Procedure Rotate(ByAngle: Integer); // 2-й метод класса
End;
• Объявим и создадим экземпляр класса, выделив под него память: