Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Информатика и ВТ Брукшир.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
5.07 Mб
Скачать

7.7.2Классы

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

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

Листинги 7.6 и 7.7 показывают, как класс с именем StackOf Integers может быть определен на языках C++, С# и Java. Далее мы вкратце рассмотрим подробности этих примеров, но сейчас заметим лишь, что в каждом примере в классе StackOf Integers определены две переменные экземпляра (массив целых чисел с названием StackEntries и целое число StackPointer, которое используется для идентификации вершины стека внутри массива — см. упражнение 5 в разделе 7.4), две процедуры (с именами push и pop) и конструктор, который устанавливает максимальный объем стека при создании каждого экземпляра стека.

Листинг 7.6. Стек целых чисел (реализация на C++)1

class StackOfIntegers {private:

int *StackEntries;

int StackPointer;

int MaxStack;

public:

StackOflntegersCint Max)

{

StackEntries = new int[Max]:

StackPointer = 0:

MaxStack = Max: }

void push(int NewEntry)

{

if (StackPointer < MaxStack)

StackEntries[StackPointer++] = NewEntry; }

int pop 0

{if (StackPointer >0) return SrackEntries[--StackPointer]: } }:

Листинг 7.7. Стек целых чисел (реализация на Java и С#)

class StackOflntegers {private int[] StackEntries:

private int StackPointer;

private int MaxStack;

public StackOfIntegers(int Max) {StackEntries = new int[Max]: StackPointer = 0:

MaxStack = Max; }

public void push(int NewEntry) {if (StackPointer < MaxStack) StackEntries[StackPointer++] = NewEntry:

} public int pop О

{if (StackPointer >0) return SrackEntnes[--StackPointer]:

else return 0;

} }

Используя этот класс как шаблон, при помощи следующего оператора на Java или С# можно создать объект с именем StackOne, представляющий стек объемом до 50 целых чисел:

StackOfIntegers StackOne = new Stack0flntegers(50);

Для C++ это будет оператор StackOfIntegers Stack0ne(50):

Далее в программе в стек StackOne можно протолкнуть значение 106, применив оператор

StackOne.push(106):

или получить в переменную OldValue верхнюю запись из StackOne при помощи оператора

OldValue - StackOne.popO:

Возвращаясь к листингам 7.6 и 7.7, обратите внимание, что для обеспечения целостности структур данных в классе используется инкапсуляция. В частности, StackEntries и StackPointer определены в разделе private, тогда как методы push и pop — в разделе public. Так, внутренняя структура стека недоступна за пределами экземпляров класса. Любое обращение к стеку должно быть выполнено при помощи общих методов.

Чтобы понять важность такой защиты, предположим, что StackEntries и Stack -Poi nter определены как publ i с, и программисту требуется обратиться к третьей записи стека типа StackOf Integers. Программист, который знает, как стек реализован в памяти, может нарушить целостность стека и обратиться к массиву StackEntry напрямую, а не путем выталкивания первых двух записей. Проблема состоит в том, что в будущем программисты, обслуживающие это приложение, могут внести где-либо в программе изменения, не совместимые с этой прямой ссылкой на запись. Например, для увеличения максимального размера стека можно изменить внутреннюю организацию типа StackOf Integers с массива на связную структуру, в которой прямая ссылка, предполагающая, что стек реализован в виде массива, будет недопустима.

В завершение раздела заметим, что класс StackOfInteges в том виде, как он определен в листингах 7.6 и 7.7, иллюстрирует кульминацию темы, проходящей через всю главу, — это набор структур данных и процедур для управления ими в одном программном модуле. Действительно, концепция классов позволяет еще более расширить эту тему, так как разрешает программистам объединять структуры данных и относящиеся к ним процедуры в форме пользовательских типов данных, при помощи которых можно создавать множество экземпляров. На самом деле концепция классов является более общей, чем концепция типов данных, так как класс может состоять, в том числе, только из процедур. Или другой экстремальный случай — класс может включать только структуры данных. Таким образом, концепция классов ~ это мощный инструмент разработки программного обеспечения, при помощи которого можно проектировать и реализовывать шаблоны для программных модулей различных видов. Классы и объектно-ориентированный принцип стали основными инструментами в сегодняшнем арсенале средств разработки приложений.