WWW.DISSERS.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА

   Добро пожаловать!


Pages:     || 2 | 3 |
МИНИСТЕРСТВО ОБРАЗОВАНИЯ РОССИИ Томский политехнический университет _ УТВЕРЖДАЮ Декан АВТФ Мельников Ю.С.

“” 2002 г.

КЛАССЫ И ОБЪЕКТЫ В OBJECT PASCAL Методические указания к лабораторной работе № 134 по курсу “Программирование и основы алгоритмизации” для студентов направления 550200 “Автоматизация и управление” Томск - 2002 УДК 681.3 Классы и объекты в Object Pascal. Методические указания к лабораторной работе № 134 по курсу “Программирование и основы алгоритмизации” для студентов направления 550200 “Автоматизация и управление” Составитель Н.М. Семёнов Рецензент к.т.н., доцент Е.И. Громаков Методические указания рассмотрены и рекомендованы методическим семинаром кафедры интегрированных компьютерных систем управления “_” _ 2002 г.

Зав. кафедрой А.М. Малышенко ОГЛАВЛЕНИЕ 1 Структурное программирование.................................................... 4 1.1 Пример с клиентом............................................................. 4 1.2 Инициализация клиентов.................................................. 5 1.3 Получение адреса клиента................................................ 7 1.4 Соединение подпрограмм с данными............................. 8 2 Определение объектно - ориентированного программирования............................................................................ 9 2.1 Объекты................................................................................. 10 2.2 Классы................................................................................... 11 2.3 Наследование....................................................................... 12 2.4 Объектные поля................................................................... 13 2.5 Продолжение примера с клиентами................................ 14 2.6 Объявление переменных, представляющих экземпляр класса................................................................. 15 2.7 Обращение к элементам объекта...................................... 3 Формы как классы.............................................................................. 3.1 Создание демонстрационной формы............................... 3.2 Исследование класса формы.......................................... 4 Контрольные вопросы....................................................................... 5 Дополнительные задания................................................................. 6 Литература........................................................................................... КЛАССЫ И ОБЪЕКТЫ В OBJECT PASCAL Цель работы: Познакомить студентов с основными концепциями объектно - ориентированного программирования на примере генерирования класса, соответствующего основной форме Delphi.

Объектно - ориентированное программирование (ООП) стало естественным способом разработки сложного программного обеспечения с графическим интерфейсом пользователя. Объектно - ориентированные методы - это мощный инструмент, позволяющий разрабатывать сложные системы, устойчивые по отношению к ошибкам и допускающие последующее расширение. ООП основано на объектно - ориентированной модели, для которой объекты являются основными предметами рассмотрения. Объектно - ориентированная модель предоставляет объектам средства взаимодействия друг с другом.

Object Pascal - это объектно - ориентированный язык программирования (ООЯП), поскольку он представляет все средства для поддержки объектно - ориентированной модели программирования.

Object Pascal ещё часто называют гибридным языком, поскольку он не только поддерживает объектно - ориентированный подход к программированию, но и позволяет создавать программы в традиционном структурном стиле. Однако объектный подход сейчас является наиболее распространённым. Основанная на компонентах архитектура Delphi была бы невозможной, если бы не было объектов. Компоненты Delphi являются, по существу, просто специализированными объектами, и их функционирование определяется объектно - ориентированной архитектурой библиотеки визуальных компонентов (Visual Component Library - VCL).

1. Структурное программирование Прежде чем перейти к объектно - ориентированному программированию, может оказаться полезным взглянуть, как решаются типичные программные проблемы с использованием традиционного структурного метода.

1.1. Пример с клиентом Представим себе типичный пример образца данных, возникающих во многих приложениях: клиент. Традиционно информация о клиенте представляется как запись (record) данных, состоящая из нескольких полей, описывающих конкретного клиента:

type RCustomer = record FirstName : String [25];

LastName : String [40];

Street : String [80];

City : String [20];

State : String [2];

Zip : String [10];

LastOrder : String [10];

end;

Значение полей FirstName и LastName очевидно. Street обозначает улицу (и номер дома); City, State и Zip относятся к остальной части полного почтового адреса.

Поле LastOrder должно содержать дату в виде ‘2003 - 07 - 22’, обозначающую дату последнего размещения клиентом заказа на Вашей фирме.

Использование структуры record подразумевает, что Вы хотите рассматривать информацию о клиенте как единое целое, но с различными внутренними атрибутами:

именем, адресом и т.д.

Теперь Вы можете описать переменные типа RCustomer следующим образом:

var Cust1, Cust2 : RCustomer;

ACust : array [1..100] of RCustomer;

Теперь у вас есть два экземпляра (переменные, по обычной терминологии Паскаля) типа RCustomer, Сust1 и Cust2, а также 100 других экземпляров, объединённых в структуру массива. Вы можете использовать эти экземпляры RCustomer для хранения информации о своих клиентах.



1.2. Инициализация клиентов Как правило, одна из первых задач - это присваивание значений объявленным переменным (экземплярам, по терминологии ООП). Другими словами, надо провести инициализацию полей таким образом, чтобы они содержали информацию о Ваших реальных клиентах. Эту задачу можно выполнить, написав прямую, бесхитростную программу, заполняющую каждое поле индивидуально:

begin...

Cust1.FirstName := ‘John’;

Cust1.LastName := ‘Smith’;

Cust1.Street := ‘123 Anystreet’;

Cust1.City := ‘Anytown’;

Cust1.State := ‘CA’;

Cust1.Zip := ‘99999 - 8888’;

Cust1.LastOrder := ‘ ‘;

...

end;

Можно написать аналогичный код для всех своих компонентов, но скоро Вы обнаружите, что повторяются всё время одни и те же операции, используя разные значения экземпляра RCustomer.

Например, операции по инициализации переменной Cust2 выглядят очень похожими:

begin...

Cust2.FirstName := ‘Mary’;

Cust2.LastName := ‘Jonson’;

Cust2.Street := ‘567 FirstStreet’;

Cust2.City := ‘Anytown’;

Cust2.State := ‘NY’;

Cust2.Zip := ‘11111 - 2222’;

Cust2.LastOrder := ‘ ‘;

...

end;

Единственно важное отличие этого фрагмента от предыдущего заключено в том, что теперь идет ссылка на Cust2 и соответствующим полям приписываются другие значения.

Обычным способом работы с повторяющимися операторами, подобными приведённым, является оформление их в виде подпрограмм и передача конкретного экземпляра переменной и её полей через список параметров. Вы можете инициализировать экземпляр клиента за один шаг, используя подпрограмму Initialize, определённую и реализованную, например, следующим образом:

Procedure Initislize ( var Cust : RCustomer;

const FirstName, LastName, Street, City, State, Zip :string );

begin Cust.FirstName :=FirstName;

Cust.LastName :=LastName;

Cust.Street :=Street;

Cust.City :=City;

Cust.State :=State;

Cust.Zip :=Zip;

Cust.LastOrder := ‘ ‘;

end;

Обратите внимание, что Cust является параметром var, и любые изменения его значения будут переданы фактически переменной, указанной при вызове процедуры.

Все поля формального параметра Cust передаются в подпрограмму как аргументы.

Только переменная LastOrder инициализируется как пустая строка, сообщая о том, что от клиента не поступило ещё ни одного заказа. Вводя подпрограмму, Вы достигаете большей инкапсуляции (скрытие реализации объекта от внешних модулей) деталей инициализации.

Теперь Вы можете повторно использовать процедуру Initialize для инициализации различных переменных типа RCustomer. Обратите внимание на то, как изменяется сам подход к инициализации при превращении набора операторов программы в процедуру - от мелких деталей инициализации, которыми Вы должны заниматься каждый раз при инициализации переменной типа RCustomer, Вы переходите к более обобщённой логике инициализации, опуская при этом подробности.

Типичный вызов процедуры Initialize выглядит следующим образом:

begin...

Initialize (Cust1, ‘John’, ‘Smith’, ‘123 Anystreet’, ‘Anytown’, ‘CA’, ‘99999 - 8888’);

...

end;

Переменная, представляющая клиента Cust1, передаётся процедуре вместе с величинами, которые Вы хотите присвоить экземпляру клиента при инициализации.

Вызов подпрограммы скрывает детали инициализации. Вам не надо больше обращать внимания на детальную структуру записи при инициализации её значения. Все низкоуровневые аспекты присваивания значений соответствующим полям осуществляются внутри процедуры и скрыты от внешнего взгляда.

Подпрограмма Initialize предназначена для типа RCustomer : Вы не можете передать ей другой тип переменной и ожидать разумного результата. Строгий механизм проверки типа в Паскале не позволит Вам передать процедуре переменную типа, отличного от RCustomer. Однако, связь между типом RCustomer и процедурой Initialize не подчёркивается в определении типа. Поэтому можно и не заметить, что Вы должны использовать процедуру Initialize со всеми экземплярами RCustomer.

При необъектном подходе возникает такая проблема, как возможность для переменной типа RCustomer существовать в “неопределённом состоянии”, когда она объявлена в блоке var, но ещё не инициализирована. Неудача инициализации экземпляра RCustomer правильным образом может привести к странному поведению программы. Но в определении RCustomer нет механизма, обеспечивающего автоматическую инициализацию экземпляра типа.

Выше приведено только несколько примеров тех трудностей, которые легко могут быть преодолены при объектном подходе.

1.3. Получение адреса клиента Другая типичная операция, выполняемая с экземплярами RCustomer - это получение значений их полей, таких как адрес. Вы могли бы манипулировать каждым экземпляром отдельно, получая значения их полей, следующим образом:

var Address1, Address2, Address3 : String;

begin...

Address1 := Cust1.FirstName + ‘ ‘ + Cust1.LastName;

Address2 :=Cust1.Street;

Address3 := Cust1.City + ‘, ‘ + Cust1.State + ‘ ‘ + Cust1.Zip;

...

end;

Приведённая программа получает адрес клиента Cust1 в виде, подходящем для печати на конверте в три строки: Address1, Address2 и Address3.





Как и раньше, поскольку эту операцию придётся повторять для многих клиентов, имеет смысл оформить её в виде отдельной подпрограммы и передавать ей экземпляр клиента в виде параметра, чтобы использовать этот набор операций со многими различными клиентами. Вы можете достичь этой цели с помощью следующей демонстрационной процедуры GetAddress :

procedure GetAddress ( const Cust : RCustomer;

var Address1, Address2, Address3 :String );

begin Address1 := Cust.FirstName + ‘ ‘ + Cust.LastName;

Address2 := Cust.Street;

Address3 := Cust.City + ‘, ‘ + Cust.State + ‘ ‘ + Cust.Zip;

end;

Как и ранее, вместо “жёсткого” кодирования переменной конкретного клиента, процедура GetAddress ссылается на общую переменную Cust, передаваемую в качестве параметра. Она передаётся как параметр вида const во избежание копирования значения фактического аргумента в локальный параметр Cust во время вызова. Параметр const обеспечивает обращение к переменной как к ссылке без копирования её значения, и, кроме того, она не может быть случайно изменена внутри процедуры.

Параметры Address1, Address2 и Address3 являются выходными параметрами, через которые передаются соответствующие строки адреса. Поэтому они объявляются как параметры var и их изменённые значения могут передаваться из процедуры.

Опять, как и ранее, у Вас есть специальная подпрограмма доступа к данным, скрывающая детали реализации. Тем не менее, этот подход требует, чтобы внутренние детали описания записи были открыты, а принадлежность подпрограммы и типа записи RCustomer друг другу остаётся неочевидной.

1.4. Соединение подпрограмм с данными Пример с записями клиентов демонстрирует типичный сценарий для случая необъектного программирования. Здесь данные, запись RCustomer, определены независимо от подпрограмм, которые оперируют с этими данными: Initialize и GetAddress. Ничего в способе определения этих объектов не помогает обнаружить логическую связь между программой и данными. Вы или должны догадаться, какие подпрограммы работают вместе с этими элементами данных, или, что ещё хуже, поддаться искушению обойти подпрограммы, специально разработанные для конкретных типов данных, и начать осуществлять доступ к полям записи напрямую. В последнем случае Вы можете упустить некоторые действия, которые требуется выполнить и которые были определены внутри подпрограммы.

Другая часть проблемы с записью RCustomer состоит в том, что её определение “открыто” и её детали подвержены всем видам “злоупотреблений”. Например, ничто не может помешать кому - либо присвоить значение ‘John’ полю LastOrder. Ясно, что поле LastOrder предназначено не для хранения этого значения. Ничто в определении записи не помешает неосторожному программисту перепутать значения полей с возможными причудливыми эффектами, проявляющимися во время работы программы.

Заметьте, что данные в этом необъектноориентированном подходе пассивны и не могут активно проверить свою целостность и правильность. Переменные просто ждут своей очереди для передачи в подпрограммы. Между данными и подпрограммами существует чёткое разделение ролей: подпрограммы активны и выполняют операции с данными, данные статичны и не имеют способа воздействовать на операции, производящиеся с ними. Информация о тесной связи между конкретным типом данных и подпрограммами, которые работают только с этим типом данных, в таком подходе отсутствует.

Поскольку обе подпрограммы, Initialize и GetAddress, явно предназначены для работы с переменными типа RCustomer, это видно из реализации этих программ, будет излишним каждый раз указывать, что только экземпляры типа RCustomer могут обрабатываться этими двумя подпрограммами.

Обратите внимание, что при каждом обращении Вашей подпрограммы к конкретной записи клиента надо явно передавать ей экземпляр переменной RCustomer в качестве параметра. Что Вам действительно надо в этой ситуации, это способ автоматического объединения экземпляров клиентов с доступными операциями, которые могут выполняться с ними.

Объектно - ориентированный подход определяет, что программы и данные, с которыми они оперируют, тесно связаны между собой. Объектно - ориентированная парадигма объединяет данные с соответствующей программой, которая оперирует с этими данными, и, таким образом, создает единое цельное образование: объект.

2. Определение объектно - ориентированного программирования Объектно - ориентированное программирование может быть охарактеризовано следующими утверждениями:

ООП использует объекты как строительные блоки. Объект - это активная единица данных.

Объект - это комбинация как элементов данных, так и операций с этими элементами, упакованных вместе для удобства использования. Объединение данных и кода называется инкапсуляцией.

Каждый объект является представителем (экземпляром) определенного класса.

Во время выполнения программы объекты взаимодействуют друг с другом, вызывая методы, которые являются подпрограммами, характерными для определённого класса.

Классы связаны друг с другом соотношениями наследования, с помощью которых объекты могут расширяться и описания существующих объектов многократно использоваться при описании новых объектов. Наследование является одним из механизмов, посредством которого один класс объектов может включаться в работу другого класса объектов. Наследование представляет мощный механизм моделирования отношений, существующих в реальном мире.

Pages:     || 2 | 3 |










© 2011 www.dissers.ru - «Бесплатная электронная библиотека»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.