Лабораторная работа 1 2 лабораторная работа 2 31 лабораторная работа 3 44 лабораторная работа 4 74
Скачать 1.76 Mb.
|
4.11 Класс StackХотя класс Box полезен для иллюстрации существенных элементов класса, он имеет небольшое практическое значение. Чтобы показать действительную мощь классов, приведем более сложный пример. Как вы помните из объектно-ориентированного программирования (OOП), одним из наиболее важных его преимуществ является инкапсуляция данных и кода, который манипулирует этими данными. Механизмом, с помощью которого достигается инкапсуляция, является класс. Создавая класс, вы организуете новый тип данных, который определяет как характер данных, так и подпрограммы, используемые для манипулирования этими данными. Непротиворечивый и управляемый интерфейс с данными класса определяют методы. Таким образом, вы можете использовать класс через его методы, не беспокоясь о деталях его реализации или о том, как данные фактически управляются внутри класса. В некотором смысле, класс подобен «машине данных». Чтобы использовать машину через ее органы управления, никаких знаний о том, что происходит внутри машины, не требуется. Фактически, поскольку подробности скрыты, ее внутренняя работа может быть изменена так, как это необходимо. Пока ваш код использует класс через его методы, внутренние подробности могут изменяться, не вызывая побочных эффектов вне класса. Чтобы получить практическое приложение предшествующего обсуждения, давайте разработаем один из типичных примеров инкапсуляции – стек. Стек хранит данные, используя очередь типа LIFO («Last-In, First-Out») – последним вошел, первым вышел. То есть стек подобен стопке тарелок на столе – последняя тарелка, поставленная на стопку, снимается со стопки первой. Стеки управляются через две операции, традиционно называемые push (поместить) и pop (извлечь, вытолкнуть). Чтобы поместить элемент в вершину стека, нужно использовать операцию push. Чтобы извлечь элемент из стека, нужно использовать операцию pop. Заметим, что инкапсуляция полного механизма стека – довольно простая задача. В следующей программе класс с именем stack реализует стек целых чисел: // Этот класс определяет целый стек для хранения 10 значений class Stack { int stck[] = new int[10]; int tos; // инициализировать вершину стека Stack() { tos = -1; } // поместить элемент в стек void push(int item) { if(tos==9) System.out.println("Стек заполнен."); else stck[++tos] = item; } // Извлечь элемент из стека int pop() { if(tos < 0) { System.out.println("Стек пуст."); return 0; } else return stck[tos--]; } } Нетрудно видеть, что класс stack определяет два элемента данных и три метода. Стек целых чисел содержится в массиве stck. Этот массив индексирован переменной tos, которая всегда содержит индекс вершины стека. Конструктор stack() инициализирует tos значением -1, которое указывает, что стек пуст. Метод push() помещает элемент в стек. Чтобы извлечь элемент, вызовите метод рор(). Так как доступ к стеку выполняется через push() и рор(), тот факт, что стек содержится в массиве, не мешает использованию стека. Например, стек мог бы храниться в более сложной структуре данных, скажем, типа связного списка, а интерфейс, определенный методами push() и pop(), остался бы тем же самым. Показанный ниже класс Teststack, демонстрирует работу с классом stack. Он создает два целочисленных стека, помещает некоторые значения в каждый и затем выталкивает их. class TestStack { public static void main(String args []) { Stack mystack1 = new Stack(); Stack mystack2 = new Stack(); // поместить несколько чисел в стек for(int i=0; i<10; i++) mystack1.push(i); for(int i=10; i<20; i++) mystack2.push(i); // вытолкнуть эти числа из стека System.out.println("Стек в mystack1:"); for(int i=0; i<10; i++) System.out.println(mystack1.pop()) ; System.out.println("Стек в mystack2:"); for(int i=0; i<10; i++) System.out.println(mystack2.pop()); } } Эта программа генерирует следующий вывод: Стек в mystack1: 9 8 7 6 5 4 3 2 1 0 Стек в mystack2: 19 18 17 16 15 14 13 12 11 10 Нетрудно заметить, что содержимое каждого стека различно. Наконец, последнее замечание относительно класса stack в данной реализации возможно изменение массива stack, который содержит стек, кодом, находящимся вне класса stack, оставляя его открытым для неправильного использования или повреждений. |