Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 47
Текст из файла (страница 47)
рОЬ11с Ьоо1 15Ещрсу() ( гесогп Коз==От ) // Возвратить общую емкость стека. РОЬ11с 1пс СаРасхГУ() гесигп эссК.Ьепосй) // Возвратить количество объектов, находящихся в // настоящий момент в стеке. рой]хс 1пс Бесмнщ() ( ГЕГОГП Гсэт ) 236 часть ), язык Сз // Продемонстрировать применение класса Бсаск.
с1аяз ЯсасКВево ( зсасас то1б Маап() ( ЯсасК зГК1 = лен Ясасз(10) спаг сп," 1пс 1) // Поместить ряд символов в стек зСК1. Сопзо1е.йгасе11пе("Поместить символы А-3 в стек зГК1.")т Гог(1 От !зГК1.1зрд11(); 1++) зГК1.Розп((сЬаг) ('А' т 1)); О Создать копию стека зссК1. ЯсасК зГК2 = пеи БсасК(зГК1)т // Вывести содержимое стека зГК1. Сопзо1е.йгаге("Содержимое стека зГК1: ")т нЬ11е( !зГК1.1зкврсу() ) сп = зГК1.Рор()т Сопзо1е.йг1се(сЫ т ) Сопзо1е.йг1севапе()т Сопзо1е.йгасе("Содержимое стека зГК2: ")) нМ1е ( (зГК2.1зЕврсу() ) ( сЬ зГК2. Рор () т Сопзо1е.йгзсе(сЫ ) ) Сопяо1е. йгзсеЬ1пе ("1п" ) т Результат выполнения этой программы приведен ниже.
Поместить символы А-3 в стек зГК1. Содержимое стека зГК1: 01НСГЕВСВА Содержимое стека зГК2: 01НСРЕВСВА В классе Ясаскпево сначала конструируется первый стек (зск1), заполняемый символами. Затем этот стек используется для конструирования второго стека (зСК2). Это приводит к выполнению следующего конструктора класса БгасК: // Сконструировать объект класса ясасК иэ // существующего стека. роЬ11с Ясаск(зсасК оЫ ( // Распределить память вевогу дпя стека.
зссК = пен спят[со.зсск.ьепПГЬ]т // Скопировать элементы в новый стек. Гог(апс 1=0( 1 < оЬ.Гозт 1++) зссК[1] = оЬ.зссК(1]т Глава 8. Подробнее о методах н классах 237 // установить переменную соэ для нового стека. Соа = оЬ.Говт ) В этом конструкторе сначала распределяется достаточный объем памяти для массива, чтобы хранить в ием элементы стека, передаваемого в качестве аргумента оЬ. Затем содержимое массива, образующего стек сЬ, копируется в новый массив, после чего соответственно устанавливается переменная Соэ, содержащая индекс вершины стека.
По завершении работы конструктора новый и исходный стеки существуют как отдельные, хотя и одинаковые объекты. Вызов перегружаемого конструктора с помощью ключевого слова Иьхе Когда приходится работать с перегружаемыми конструкторами, то иногда очень полезно предоставить возможность одному конструктору вызывать другой. В С№ это дается с помощью ключевого слова сй1э. Ниже приведена общая форма такого вызова. имя конструктора(список параметрсв1) СМэ(список параметров2) ( // ... Тело конструктора, // которое может быть пустым. В исходном конструкторе сначала выполняется перегружаемый конструктор, список параметров которого соответствует критерию список параметров2, а затем все остальные операторы, если таковые имеются в исходном конструкторе. Ниже приведен соответствующий пример.
// Продемонстрировать выэов конструктора с помощью // ключевого слова СЫв. паапа Эуэгепц с1аээ Хусоогб ( рпЫТс хпс х, ут рпЫ1с ХУСоогб() : СЬ1в(0, О) ( Сопэо1е.нг1геьапе("В конструкторе ХТСоогб()")т ) рпЫьс хтСоогб (хуСоогб оЬб): сььэ (оЬб . х, оЬб . у) ( Сопэо1е.нгасеььпе("В конструкторе Хтсоогб(оют)")т ) рпЫ1с ХТСоогб(1пс 1, ьпс 3) ( Сопво1е.игхаеььпе("В конструкторе ХТСоогб(ьпг, 1пг)"); х 1) у=э! ) ) 238 Часть). Язык С№ с1азз Очег1оас(санзвено ( зсасгс тога ма1п() ХХСоогй С1 = пен Хусоогс((); ХХСоогс( С2 пен Хтсоога(8, 9) Хтсоога СЗ = пен Хтсоого(С2)з Сопно1е.иг1Сеь1пе("С1.х, С1.у. "" + С1.х + С1.у); Сопзо1е.нг1Сеьспе("С2.х, С2.у: " + С2.х + т с2.у) з Сопно1е.нг1геь1пе("СЗ.х, Сз.у: " + Сз.х + ь сз.у) з Выполнение этого кода приводит к следуюшему результату; В конструкторе В конструкторе В конструкторе В конструкторе В конструкторе С1.х, С1.у: О, С2.х, С2.у: 8, Сз.х, Сз.у: 8, Хусоога(1пг, 1пс) Хтсоога() Хтсоогс((1пС, гпг) Хтсоогс((1пС, гпг) Хтсоогп(оЬЗ) О 9 9 рпкъгс Хусоога (1пг х): Съьз (х, х) ( ) По умолчанию в этом конструкторе для координаты у автоматически устанавливается то же значение, что и для координаты у.
Конечно, пользоваться такими конструкциями с задаваемыми "по умолчанию" аргументами следует благоразумно и осторожно, чтобы не ввести в заблуждение пользователей классов. Инициализаторы обьектов В версии С№ 3.0 введено новое средство, называемое инициализаторами объектов, которое предоставляет еше один способ создания объекта и инициализации его полей Код в приведенном выше примере работает следующим образом. Единственным конструктором, фактически инициализирующим поля х и у в классе хтсоогс), является конструктор хусоогс( (1ПС, 1ПС) .
А два других конструктора просто вызывают этот конструктор с помоШью ключевого слова С)11з. Например, когда создается объект с1, то вызывается его конструктор ХХСоогс) (), что приводит к выполнению вызова Сй№з (О, О), который в данном случае преобразуется в вызов конструктора хгсоогс) (О, О) . То же самое происходит и при создании объекта с2. Вызывать перегружаемый конструктор с помошью ключевого слова с)11з полезно, в частности, потому, что он позволяет исключить ненужное дублирование кода. В приведенном выше примере нет никакой необходимости дублировать во всех трех конструкторах одну и ту же последовательность инициализации, и благодаря применению ключевого слова сп18 такое дублирование исключается.
Другое преимушество организации подобного вызова перезагружаемого конструктора заключается в возможности создавать конструкторы с задаваемыми "по умолчанию" аргументами, когда эти аргументы не указаны явно. Ниже приведен пример создания еше одного конструктора ххсоогс1 Глава 8. Подробнее о методах и классах 239 и свойств. (Подробнее о свойствах речь пойдет в главе 10.) Если используются инициализаторы объектов, то вместо обычного вызова конструктора класса указываются имена полей или свойств, инициализируемых первоначально задаваемым значением. Следовательно, синтаксис инициализатора объекта предоставляет альтернативу явному вызову конструктора класса.
Синтаксис инициализатора объекта используется главным образом при создании анонимных типов в ьк)чО-выражениях. (Подробнее об анонимных типах и ькХО-выражениях — в главе 19.) Но поскольку инициализаторы объектов мощно, а иногда и должно использовать в именованном классе, то ниже представлены основные положения об инициализации объектов. Обратимся сначала к простому примеру: // Простой пример, демонстрирующий применение // инициализаторов объектов, цяхпо Яуяселц с1авв МуС1авв ( рцЬ11с 1пс Соцпкт роъъкс вттупо Ясх," с1авя ОЬ01п1кпеюо ( вкакхс тоюд Макп() ( // Сконструировать объект типа МуС1аяв, используя // инициализаторы объектов.
муС1авв оЬЯ = пен мус1авя ( соцпс = 100, ясг = "тестирование" )т сопяо1е.иххсеьхпе(оь).соцпс т " " + оь).зкт)т ) Выполнение этого кода дает следующий результат: 100 Тестирование Как показывает результат выполнения приведенного выше кода, переменная экземпляра оЬ) .Соцпб инициализирована значением 100, а переменная экземпляра оЬ1. Ясг — символьной строкой "Тестирование".
Но обратите внимание на то, что в классе МуС1азя отсутствуют явно определяемые конструкторы и не используется обычный синтаксис конструкторов. Вместо этого объект оЬ) класса мус1азз создается с помощью следующей строки кода: мус1авя оь) = пен мус1авв ( соцпс = 100, яск = "тестирование" ); В этой строке кода имена полей указываются явно вместе с их первоначальными значениями. Это приводит к тому, что сначала конструируется экземпляр объекта типа мус1аяя (с помощью неявно вызываемого по умолчанию конструктора), а затем задаются первоначальные значения переменных соцпс и яьд данного экземпляра.
Следует особо подчеркнуть, что порядок указания инициализаторов особого значения не имеет. Например, объект оЬл можно было бы инициализировать и так, как показано ниже. мус1авв оь) = пен мус1авв ( ятт = "тестирование", соцпс 100 ); 240 Часть (. Язык С() В этой строке кода инициализация переменной экземпляра зсг предшествует ииициализации переменной экземпляра соэпс, а в приведенном выше коде все происходило наоборот. Но в любом случае результат получается одинаковым.
Ниже приведена общая форма синтаксиса инициализации объектов. оен имя класса (имя = вырвжеиие, имя = выражение, ... ). где имя обозначает имя поля или свойства, т.е. доступного члена класса, иа который указывает имя класса. А выражение обозначает инициализирующее выражение, тиц которого, конечно, должен соответствовать типу поля или свойства. Ииициализаторы объектов обычно ие используются в имеиоваииых классах, как, иапример, в представленном выше классе МуС1аээ, хотя это вполне допустимо. Вообще, при обращении с именованными классами используется синтаксис вызова обычного коиструктора. И, как упоминалось выше, ииициализаторы объектов применяются в основиом в аиоиимиых типах, формируемых в ].1]ь]Я-выражеииях. Метод махп () В представленных до сих пор примерах программ использовалась одна форма метода Маъо О.
Но у него имеется также целый ряд перегружаемых форм. Одни из иих могут служить для возврата значений, другие — для получения аргументов. В этом разделе рассматриваются и те и другие формы. Возврат значений из метода ма~а () По завершении программы имеется возможность возвратить конкретное значение из метода мауп ( ) вызывающему процессу (зачастую операционной системе). Для этой цели служит следующая форма метода ма1п (): всасьс ьос Маго() Обратите внимание иа то, что в этой форме метода ма1п () объявляется возвращаемый тип 1пс вместо типа чоЫ.