WWW.DISSERS.RU

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

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


Pages:     || 2 | 3 | 4 | 5 |   ...   | 9 |
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ ИВАНОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ КАФЕДРА ВЫЧИСЛИТЕЛЬНОЙ И ПРИКЛАДНОЙ МАТЕМАТИКИ РАЗРАБОТКА КЛАССОВ НА ЯЗЫКЕ OBJECT PASCAL Методические указания к курсу компьютерных наук Иваново Издательство «Ивановский государственный университет» 2007 Составитель: доцент кафедры вычислительной и прикладной математики Е. В. Соколов Приводятся примеры разработки классов на языке Object Pascal, являющемся частью среды программирования Borland Delphi. Обсуждаются такие вопросы, как создание интерфейса, реализация и использование классов-контейнеров, наследование классов. Предназначается студентам 2 курса математического факультета, обучающимся по специальности/направлению «Математика» и направлению «Математика. Компьютерные науки».

Печатается по решению методической комиссии математического факультета Ивановского государственного университета Рецензент кандидат физико-математических наук, профессор Н. И. Яцкин © Издательство «Ивановский государственный университет», 2007 СОДЕРЖАНИЕ Введение...................................................................................................... 4 § 1. Библиотеки подпрограмм................................................................. 5 Задача 1.1................................................................................................ 5 § 2. Простейшие классы-контейнеры.................................................. 12 Задача 2.1.............................................................................................. 12 Задача 2.2.............................................................................................. 18 Задача 2.3.............................................................................................. 25 Задача 2.4.............................................................................................. 39 § 3. Универсальные контейнеры.......................................................... Задача 3.1.............................................................................................. § 4. Иерархии классов............................................................................. Задача 4.1.............................................................................................. Задача 4.2.............................................................................................. Вместо заключения................................................................................. Приложение 1. Библиотека для работы с рациональными числами..... Приложение 2. Класс Number.................................................................. Приложение 3. Класс Rational.................................................................. ВВЕДЕНИЕ Настоящие методические указания продолжают пособие автора [*] Введение в объектно-ориентированное программирование на языке Object Pascal. Иваново: ИвГУ, 2005.

Они содержат примеры решения задач, иллюстрирующие понятия и методы программирования, рассмотренные в первых трех частях этого пособия.

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

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

Задача 2.1 показывает, как преобразовать созданную ранее библиотеку в класс для представления целочисленных векторов. Далее полученный класс постепенно усложняется. Сначала компонентами вектора становятся записи, представляющие рациональные числа (задача 2.2), затем — объекты класса Rational, содержательно имеющие тот же смысл (зад ача 2.3). Наконец, в задаче 2.4 снимается ограничение на длину вектора.

Для реализации последнего класса используются динамические массивы, необходимые сведения о которых приводятся прямо в ходе решения.

В третьем параграфе описанная серия продолжается задачей построения класса для представления векторов, компоненты которых могут иметь произвольный (почти) тип. Решение этой задачи уже требует приемов объектно-ориентированного программирования. В частности, оно использует такое специальное средство языка Object Pascal, как классовые ссылки, объявление, внутренняя структура и использование которых рассматриваются в начале параграфа.

Наконец, в четвертом параграфе строятся два класса, аналогичных Rational, объекты которых служат для представления целых чисел и цветов в формате RGB. Задача 4.1 иллюстрирует разработку производных классов и некоторые возникающие при этом проблемы. В задаче 4.указанные классы используются для того, чтобы в полном объеме продемонстрировать возможности контейнера из задачи 3.1, а также использование классовых ссылок для обобщенного программирования.

1. Б ИБЛИОТЕКИ ПОДПРОГРАММ Этот параграф описывает процесс разработки библиотек подпрограмм и является вспомогательным. Построенная в нем библиотека будет использована в следующем параграфе для создания класса, имеющ его аналогичную функциональность.

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

1) вычисление суммы двух векторов, 2) вычисление разности двух векторов, 3) вычисление скалярного произведения двух векторов, 4) прибавление одного вектора к другому, 5) вычитание одного вектора из другого, 6) присваивание одного вектора другому, 7) сравнение двух векторов на равенство, 8) вычисление длины вектора (как элемента n-мерного евклидова пространства), 9) преобразование вектора в строковую форму для вывода на экран или в файл.



Библиотеку следует оформить в виде модуля. Требуется также создать программу, использующую данный модуль и демонстрирующую работу его открытых подпрограмм.

Схема решения.

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

2. Объявление подпрограмм, т. е. определение их имен, списков параметров и типов возвращаемых значений.

3. Реализация подпрограмм.

4. Размещение написанного кода внутри модуля.

5. Создание программы, демонстрирующей работу открытых процедур и функций библиотеки.

Решение. 1. Прежде всего необходимо определиться с типом данных, который будет использоваться для представления векторов.

Очевидно, что простые типы языка Object Pascal для этой цели не подходят уже хотя бы потому, что занимают фиксированный объем памяти.

Размер же вектора зависит от числа n и, вообще говоря, может быть сколь угодно большим. Поэтому следует использовать один из составных типов: запись (record), массив (array) или множество (set).

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

const Dim = n; // вместо n необходимо указать конкретное целое число type IVector = array[1..Dim] of Integer;

2. Перейдем теперь к объявлению процедур и функций. Здесь основную роль играет содержательный смысл выполняемых ими действий.

Вычисление суммы и разности — бинарные операции на множестве векторов размерности n. Поэтому соответствующие подпрограммы будут функциями с двумя параметрами типа IVector и возвращаемыми значениями типа IVector:

function Plus (v1, v2: IVector): IVector; // вычисление суммы function Minus(v1, v2: IVector): IVector; // вычисление разности Скалярное произведение — также функция двух аргументов, яв ляющихся векторами, но ее значение — это число, получающееся из компонент векторов последовательностью операций сложения и умножения. Поскольку мы рассматриваем векторы с целочисленными компонентами, результат выполнения данной последовательности снова будет целым числом:

function ScalarProduct(v1, v2: IVector): Integer;

Подпрограммы 4–6, осуществляющие прибавление, вычитание и присваивание, отличаются от вышеприведенных в первую очередь тем, что изменяют один из своих аргументов. Следовательно, этот аргумент должен быть объявлен как передаваемый по ссылке (var-параметр). Кроме того, в языке Object Pascal оператор присваивания не возвращает значения, поэтому в нашем случае реализующая его подпрограмма должна быть процедурой. Поскольку прибавление и вычитание — это арифметические операторы с присваиванием, к ним могут быть прим енены те же соображения. Тем самым, получаем следующие объявления:

procedure Add (var v1, v2: IVector); // прибавление procedure Subtract(var v1, v2: IVector); // вычитание procedure Assign (var v1, v2: IVector); // присваивание Операцию сравнения на равенство можно рассматривать как функцию двух векторов, возвращающую булевское значение. Отсюда немедленно вытекает ее объявление:

function AreEqual(v1, v2: IVector): Boolean;

Наконец, определение длины вектора и преобразование его в строку — это, очевидно, функции одного аргумент а. В первом случае значением функции будет число, причем не обязательно целое, так как для его вычисления используется операция извлечения квадратного корня:

function GetLength(v: IVector): Real;

Вторая функция, естественно, возвращает строку, содержащую результат преобразования:

function AsString(v: IVector): String;

3. Итак, все процедуры и функции объявлены и мы можем приступить к их реализации, которая, впрочем, совершенно тривиальна.

Пример 1.1.1. Реализация подпрограмм задачи 1.1.

function Plus(v1, v2: IVector): IVector;

var i: Integer;

begin for i:=1 to Dim do result[i]:=v1[i]+v2[i]; end;

function Minus(v1, v2: IVector): IVector;

var i: Integer;

begin for i:=1 to Dim do result[i]:=v1[i]-v2[i]; end;

procedure Add(var v1, v2: IVector);

var i: Integer;

begin for i:=1 to Dim do v1[i]:=v1[i]+v2[i]; end;

procedure Subtract(var v1, v2: IVector);

var i: Integer;

begin for i:=1 to Dim do v1[i]:=v1[i]-v2[i]; end;

function ScalarProduct(v1, v2: IVector): Integer;

var i: Integer;

begin result:=0; for i:=1 to Dim do result:=result+v1[i]*v2[i]; end;

function GetLength(v: IVector): Real;

var i: Integer;

begin result:=0; for i:=1 to Dim do result:=result+sqr(v[i]);

result:=sqrt(result);





end;

function AreEqual(v1, v2: IVector): Boolean;

var i: Integer;

begin result:=true;

for i:=1 to Dim do if v1[i]<>v2[i] then result:=false;

end;

procedure Assign(var v1, v2: IVector);

var i: Integer;

begin for i:=1 to Dim do v1[i]:=v2[i]; end;

function AsString(v: IVector): String;

var i: Integer;

begin result:='(';

for i:=1 to Dim do begin result:=result+IntToStr(v[i]);

if i

end;

result:=result+')';

end;

Подпрограммы Plus, Minus, Add и Subtract в цикле выполняют покомпонентные операции сложения или вычитания. Разница лишь в том, что функции Plus и Minus сохраняют результат в переменной result, возвращаемой в качестве их значения, а процедуры Add и Subtract — в первом аргументе v1. Так как тип IVector — это массив, то к компонентам переменных данного типа мы можем обращаться обычным образом — с помощью индексирования.

Поскольку |v| = vv, неудивительно, что реализации функций ScalarProduct и GetLength очень похожи. В обоих переменная result инициализируется нулем и затем в цикле накапливает сумму покомпонентных произведений. В функции GetLength из полученного значения требуется дополнительно извлечь квадратный корень.

Критерий равенства двух векторов можно сформулировать следующим образом: векторы не равны, если хотя бы для одной пары соответственных компонент этих векторов имеет место неравенство, и рав ны в противном случае. Данное определение и реализует функция AreEqual: если хотя бы для одного i выражение v1[i]<>v2[i] оказывается истинным, в переменную result записывается значение false, если же для всех i указанное выражение ложно, переменная result сохраняет значение, полученное ею до начала выполнения цикла, т. е. true.

Функция AsString применяет к каждой компоненте вектора библиотечную функцию IntToStr, которая переводит целое число в десятичную систему счисления и возвращает результат в виде ASCII-строки, символы которой соответствуют цифрам десятичной записи. Из полученных таким образом значений функция AsString формирует одну строку, вставляя между компонентами вектора запятые и заключая всю последовательность в круглые скобки. Разумеется, такой формат не является единственно возможным. Заметим также, что для использования функции IntToStr необходимо подключить модуль SysUtils.

4. Теперь полученную библиотеку необходимо оформить в виде модуля. Единственный содержательный момент здесь заключается в том, чтобы определить, какие элементы модуля сделать открытыми, а какие закрытыми. В нашем случае этот вопрос решается однозначно:

1) поскольку вспомогательных подпрограмм библиотека не содержит, все ее процедуры и функции должны быть открытыми;

2) тип IVector, необходимый для объявления подпрограмм, также должен быть открытым;

3) константа, задающая размерность векторов, предшествует определению типа и, следовательно, заведомо находится в разделе интерфейса, т. е. открыта.

Таким образом, все объявления необходимо разместить в разделе интерфейса, а реализацию подпрограмм — в разделе реализации. Модуль SysUtils, о котором шла речь выше, необходим лишь для реализации функции AsString. Поэтому его лучше подключить в разделе реализации (см. обсуждение этого вопроса в § 1.3 из [*]). В результате мы получаем следующий код.

Пример 1.1.2. Структура модуля из задачи 1.1.

unit UnitIVector;

interface const Dim = 5;

type IVector = array[1..Dim] of Integer;

function Plus (v1, v2: IVector): IVector;

function Minus (v1, v2: IVector): IVector;

function ScalarProduct(v1, v2: IVector): Integer;

function AreEqual (v1, v2: IVector): Boolean;

procedure Add (var v1, v2: IVector);

procedure Subtract(var v1, v2: IVector);

procedure Assign (var v1, v2: IVector);

function GetLength(v: IVector): Real;

function AsString(v: IVector): String;

implementation uses SysUtils;

// Здесь размещается реализация подпрограмм, // приведенная в примере 1.1.1.

end.

5. Последнее, что нам необходимо сделать, это разработать демонстрационную программу. Ее код может выглядеть примерно так.

Пример 1.1.3. Демонстрационная программа для задачи 1.1.

program TestIVector;

{$APPTYPE CONSOLE} uses UnitIVector in 'UnitIVector.pas';

var v1, v2, v3, v4: IVector; i: Integer;

begin for i:=1 to Dim do begin v1[i]:=i+1; v2[i]:=i+2;

end;

WriteLn('v1: '+AsString(v1));

WriteLn('v2: '+AsString(v2));

WriteLn('GetLength(v1): ', GetLength(v1):5:5);

v3:=Plus(v1, v2); WriteLn('v3 after v3:=Plus(v1, v2): '+AsString(v3));

Add(v1, v2); WriteLn('v1 after Add(v1, v2): '+AsString(v1));

if AreEqual(v1, v3) then WriteLn('v1 is equal to v3') else WriteLn('v1 is not equal to v3');

Assign(v4, v2); WriteLn('v4 after Assign(v4, v2): '+AsString(v4));

Subtract(v4, v1);

WriteLn('v2 after v4.Subtract(v1): '+AsString(v2));

WriteLn('v4 after v4.Subtract(v1): '+AsString(v4));

WriteLn('ScalarProduct(v2, v4): ', ScalarProduct(v2, v4));

ReadLn;

end.

После подключения модуля UnitIVector константа Dim, тип IVector и подпрограммы библиотеки становятся доступны так же, как если бы они были объявлены в самой программе. В основном блоке после инициализации компонент векторов v1 и v2 над этими векторами выполняется ряд операций, каждая из которых завершается выводом результата на экран. Строка WriteLn('v2 after v4.Subtract(v1): '+AsString(v2));

Pages:     || 2 | 3 | 4 | 5 |   ...   | 9 |










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

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