Полное руководство. С# 4.0 - Шилдт Герберт
Шрифт:
Интервал:
Закладка:
Метод IsFull() возвращает логическое значение true, если стек заполнен, а иначе — логическое значение false. Метод IsEmpty() возвращает логическое значениеtrue, если стек пуст, а иначе — логическое значение false. Для получения общей емкости стека (т.е. общего числа элементов, которые могут в нем храниться) достаточновызвать метод Capacity(), а для получения количества элементов, хранящихся в настоящий момент в стеке, — метод GetNum(). Польза этих методов состоит в том, чтодля получения информации, которую они предоставляют, требуется доступ к закрытой переменной tos. Кроме того, они служат наглядными примерами организациибезопасного доступа к закрытым членам класса с помощью открытых методов.
Конкретное применение класса Stack для реализации стека демонстрируетсяв приведенной ниже программе.// Продемонстрировать применение класса Stack.using System;// Класс для хранения символов в стеке.class Stack { // Эти члены класса являются закрытыми. char[] stck; // массив, содержащий стек int tos; // индекс вершины стека // Построить пустой класс Stack для реализации стека заданного размера. public Stack (int size) { stck = new char[size]; // распределить память для стека tos = 0; } // Поместить символы в стек. public void Push(char ch) { if(tos==stck.Length) { Console.WriteLine(" - Стек заполнен."); return; } stck[tos] = ch; tos++; } // Извлечь символ из стека. public char Pop() { if(tos==0) { Console.WriteLine(" - Стек пуст."); return (char) 0; } tos--; return stck[tos]; } // Возвратить значение true, если стек заполнен. public bool IsFull() { return tos==stck.Length; } // Возвратить значение true, если стек пуст. public bool IsEmpty() { return tos==0; } // Возвратить общую емкость стека. public int Capacity() { return stck.Length; } // Возвратить количество объектов, находящихся в данный момент в стеке. public int GetNum() { return tos; }}class StackDemo { static void Main() { Stack stk1 = new Stack(10); Stack stk2 = new Stack(10); Stack stk3 = new Stack(10); char ch; int i; // Поместить ряд символов в стек stk1. Console.WriteLine("Поместить символы А-J в стек stk1."); for(i=0; !stk1.IsFull(); i++) stk1.Push((char) ('A' + i)); if(stk1.IsFull()) Console.WriteLine("Стек stk1 заполнен."); // Вывести содержимое стека stk1. Console.Write("Содержимое стека stk1: "); while( !stk1.IsEmpty() ) { ch = stk1.Pop(); Console.Write(ch); } Console.WriteLine(); if(stk1.IsEmpty()) Console.WriteLine("Стек stk1 пуст.n"); // Поместить дополнительные символы в стек stk1. Console.WriteLine("Вновь поместить символы A-J в стек stk1."); for(i=0; !stk1.IsFull(); i++) stk1.Push((char) ('A' + i)); // А теперь извлечь элементы из стека stk1 и поместить их в стек stk2. // В итоге элементы сохраняются в стеке stk2 в обратном порядке. Console.WriteLine("А теперь извлечь символы из стека stk1n" + "и поместить их в стек stk2."); while( !stk1.IsEmpty() ) { ch = stk1.Pop(); stk2.Push(ch); } Console.Write("Содержимое стека stk2: "); while( !stk2.IsEmpty() ) { ch = stk2.Pop(); Console.Write(ch); } Console.WriteLine("n"); // Поместить 5 символов в стек. Console.WriteLine("Поместить 5 символов в стек stk3."); for(i=0; i < 5; i++) stk3.Push((char) ('A' + i)); Console.WriteLine("Емкость стека stk3: " + stk3.Capacity()); Console.WriteLine("Количество объектов в стеке stk3: " + stk3.GetNum()); }}При выполнении этой программы получается следующий результат.
Поместить символы А-J в стек stk1.Стек stk1 заполнен.Содержимое стека stk1: JIHGFEDCBAСтек stk1 пуст.Вновь поместить символы А-J в стек stk1.А теперь извлечь символы из стека stk1и поместить их в стек stk2.Содержимое стека stk2: ABCDEFGHIJПоместить 5 символов в стек stk3.Емкость стека stk3: 10Количество объектов в стеке stk3: 5## Передача объектов методам по ссылкеВ приведенных до сих пор примерах программ при указании параметров, передаваемых методам, использовались типы значений, например int или double. Но вметодах можно также использовать параметры ссылочного типа, что не только правильно, но и весьма распространено в ООП. Подобным образом объекты могут передаваться методам по ссылке. В качестве примера рассмотрим следующую программу.
// Пример передачи объектов методам по ссылке.using System;
class MyClass { int alpha, beta; public MyClass(int i, int j) { alpha = i; beta = j; } // Возвратить значение true, если параметр ob // имеет те же значения, что и вызывающий объект. public bool SameAs(MyClass ob) { if((ob.alpha == alpha) & (ob.beta == beta)) return true; else return false; } // Сделать копию объекта ob. public void Copy(MyClass ob) { alpha = ob.alpha; beta = ob.beta; } public void Show() { Console.WriteLine("alpha: (0), beta: (1}", alpha, beta); }}
class PassOb { static void Main() { MyClass ob1 = new MyClass(4, 5); MyClass ob2 = new MyClass(6, 7); Console.Write("ob1: "); ob1.Show(); Console.Write("ob2: "); ob2.Show(); if(ob1.SameAs(ob2)) Console.WriteLine("ob1 и ob2 имеют одинаковые значения."); else Console.WriteLine("ob1 и ob2 имеют разные значения."); Console.WriteLine(); // А теперь сделать объект ob1 копией объекта ob2. ob1.Copy(ob2); Console.Write("оЫ после копирования: "); ob1.Show(); if(ob1.SameAs(ob2)) Console.WriteLine("ob1 и ob2 имеют одинаковые значения."); else Console.WriteLine("ob1 и ob2 имеют разные значения."); }}Выполнение этой программы дает следующий результат.
ob1: alpha: 4, beta: 5ob2: alpha: 6, beta: 7ob1 и ob2 имеют разные значения.ob1 после копирования: alpha: 6, beta: 7ob1 и оb2 имеют одинаковые значения.Каждый из методов SameAs() и Сору() в приведенной выше программе получает ссылку на объект типа MyClass в качестве аргумента. Метод SameAs() сравниваетзначения переменных экземпляра alpha и beta в вызывающем объекте со значениями аналогичных переменных в объекте, передаваемом посредством параметра ob.Данный метод возвращает логическое значение true только в том случае, если обаобъекта имеют одинаковые значения этих переменных экземпляра. А метод Сору()присваивает значения переменных alpha и beta из объекта, передаваемого по ссылкепосредством параметра ob, переменным alpha и beta из вызывающего объекта. Какпоказывает данный пример, с точки зрения синтаксиса объекты передаются методампо ссылке таким же образом, как и значения обычных типов.### Способы передачи аргументов методуКак показывает приведенный выше пример, передача объекта методу по ссылкеделается достаточно просто. Но в этом примере показаны не все нюансы данного процесса. В некоторых случаях последствия передачи объекта по ссылке будут отличатьсяот тех результатов, к которым приводит передача значения обычного типа. Для выяснения причин этих отличий рассмотрим два способа передачи аргументов методу.Первым способом является вызов по значению. В этом случае значение аргументакопируется в формальный параметр метода. Следовательно, изменения, вносимые впараметр метода, не оказывают никакого влияния на аргумент, используемый для вызова. А вторым способом передачи аргумента является вызов по ссылке. В данном случаепараметру метода передается ссылка на аргумент, а не значение аргумента. В методеэта ссылка используется для доступа к конкретному аргументу, указываемому при вызове. Это означает, что изменения, вносимые в параметр, будут оказывать влияние нааргумент, используемый для вызова метода.По умолчанию в C# используется вызов по значению, а это означает, что копия аргумента создается и затем передается принимающему параметру. Следовательно, припередаче значения обычного типа, например int или double, все, что происходит спараметром, принимающим аргумент, не оказывает никакого влияния за пределамиметода. В качестве примера рассмотрим следующую программу.
// Передача аргументов обычных типов по значению.using System;class Test { / Этот метод не оказывает никакого влияния на аргументы, используемые для его вызова. / public void NoChange(int i, int j) { i = i + j; j = -j; }}