Страница 87 из 502
Стек служит классическим примером объектно-ориентированного программирования потому, что он сочетает в себе средства хранения информации с методами доступа к ней. Для реализации такого сочетания отлично подходит класс, в котором члены, обеспечивающие хранение информации в стеке, должны быть закрытыми, а методы доступа к ним — открытыми. Благодаря инкапсуляции базовых средств хранения информации соблюдается определенный порядок доступа к отдельным элементам стека из кода, в котором он используется.
Для стека определены две основные операции: поместить данные в стек и извлечь их оттуда. Первая операция помещает значение на вершину стека, а вторая — извлекает значение из вершины стека. Следовательно, операция извлечения является безвозвратной: как только значение извлекается из стека, оно удаляется и уже недоступно в стеке.
В рассматриваемом здесь примере создается класс Stack, реализующий функции стека. В качестве базовых средств для хранения данных в стеке служит закрытый массив. А операции размещения и извлечения данных из стека доступны с помощью открытых методов класса Stack. Таким образом, открытые методы действуют по упомянутому выше принципу "последним пришел — первым обслужен". Как следует из приведенного ниже кода, в классе Stack сохраняются символы, но тот же самый механизм может быть использован и для хранения данных любого другого типа.
<b>// Класс для хранения символов в стеке.</b>
<b>using System;</b>
<b>class Stack {</b>
<b> // Эти члены класса являются закрытыми, </b>
<b> char[] stck; // массив, содержащий стек </b>
<b> int tos; // индекс вершины стека</b>
<b> // Построить пустой класс Stack для реализации стека заданного размера, </b>
<b> public Stack(int size) {</b>
<b> stck = new char[size]; // распределить память для стека </b>
<b> tos = 0;</b>
<b> }</b>
<b> // Поместить символы в стек, </b>
<b> public void Push(char ch) { </b>
<b> if(tos==stck.Length) {</b>
<b> Console.WriteLine(" - Стек заполнен."); </b>
<b> return;</b>
<b> }</b>
<b> stck[tos] = ch; </b>
<b> tos++;</b>
<b> }</b>
<b> // Извлечь символ из стека, </b>
<b> public char Pop() {</b>
<b> if(tos==0) {</b>
<b> Console.WriteLine(" - Стек пуст."); </b>
<b> return (char) 0;</b>
<b> }</b>
<b> tos-- ;</b>
<b> return stck[tos];</b>
<b> }</b>
<b> // Возвратить значение true, если стек заполнен, </b>
<b> public bool IsFull() { </b>
<b> return tos==stck.Length;</b>
<b> }</b>
<b> // Возвратить значение true, если стек пуст, </b>
<b> public bool IsEmpty() { </b>
<b> return tos==0;</b>
<b> }</b>
<b> // Возвратить общую емкость стека, </b>
<b> public int Capacity() {</b>
<b> return stck.Length;</b>
<b> }</b>
<b> // Возвратить количество объектов, находящихся в данный момент в стеке, </b>
<b> public int GetNum() { </b>
<b> return tos;</b>
<b> }</b>
<b>}</b>
Рассмотрим класс Stack более подробно. В начале этого класса объявляются две следующие переменные экземпляра.
<b>// Эти члены класса являются закрытыми, </b>
<b>char[] stck; // массив, содержащий стек </b>
<b>int tos; // индекс вершины стека</b>
Массив stck предоставляет базовые средства для хранения данных в стеке (в данном случае — символов). Обратите внимание на то, что память для этого массива не распределяется. Это делается в конструкторе класса Stack. А член tos данного класса содержит индекс вершины стека.
Оба члена, tosnstck, являются закрытыми, и благодаря этому соблюдается принцип "последним пришел — первым обслужен". Если же разрешить открытый доступ к члену stck, то элементы стека окажутся доступными не по порядку. Кроме того, член tos содержит индекс вершины стека, где находится первый обслуживаемый в стеке элемент, и поэтому манипулирование членом tos в коде, находящемся за пределами класса Stack, следует исключить, чтобы не допустить разрушение самого стека. Но в то же время члены stckntos доступны пользователю класса Stack косвенным образом с помощью различных отрытых методов, описываемых ниже.
Рассмотрим далее конструктор класса Stack.