Г. Шилдт - С#4.0 Полное руководство (1160795), страница 39
Текст из файла (страница 39)
Исходный массив: Это очень простой тест. Видоизмененный массив: Это тоже простой до предела тест! Рассмотрим более интересный пример. В приведенной ниже программе целое число выводится словами. Например, число 19 выводится словами "один девять". // Вывести отдельные цифры целого числа словами. оя1пд Эуягепц с1аяя Сопчеттоьдьтятоиогдя ( ятаттс чо1г( Ма1п() ( Ьпг пцш; гпг пехго1911; 1пт пцшо191тя; гпг[] и = пен гпг(20]; ятг1п9[] о191тя = ( "нуль", "один", "два", "три", "четыре", "пять", "шесть", "семь", "восемь", "девять" ); пцш = 1908; Сопяо1е.иг1теЬ1пе("Число: " + пцш); Сопво1е.нтгте("Число словами: "); пехто1911 = 0; поит)191гя = 0; // Получить отдельные цифры и сохранить их в массиве и.
Глава т. Массивы и строки 205 !! Эти цифры сохраняются в обратном порядке. бо ( пехгб1911 = пцв Ь 10; п[пцвб191тв) = пехгг(19111 пцвбюаьья+Ю пцв = пцв У 10; ) нп11е(пцв > 0); пцвь)1911в--; !! Вывести полученные слова. Гог(; пцвьцаьов >= 0; пцвс1911в--) Сопво1е.альте(б191пв[п[пцвсьчьгв)) Сопво1е.игзве11пе()1 Выполнение этой программы приводит к следующему результату.
Число: 1908 Число словами: один девять нуль восемь В данной программе использован массив строк с[191гв для хранения словесных обозначений цифр от О до 9. По ходу выполнения программы целое число преобразуется в слова. Для этого сначала получаются отдельные цифры числа, а затем они сохраняются в обратном порядке следования в массиве и типа 1пс. После этого выполняется циклический опрос массива и в обратном порядке. При этом каждое целое значение из массива и служит в качестве индекса, указывающего на слова, соответствующие полученным цифрам числа и выводимые как строки. Постоянство строк Как ни странно, содержимое объекта типа вбг1пд не подлежит изменению. Это означает, что однажды созданную последовательность символов изменить нельзя. Но данное ограничение способствует более эффективной реализации символьных строк. Поэтому этот, на первый взгляд, очевидный недостаток на самом деле превращается в преимущество.
Так, если требуется строка в качестве разновидности уже имеющейся строки, то для этой цели следует создать новую строку, содержащую все необходимые изменения. А поскольку неиспользуемые строковые объекты автоматически собираются в "мусор", то о дальнейшей судьбе ненужных строк можно даже не беспокоиться. Следует, однако, подчеркнуть, что переменные ссылки на строки (т.е. объекты типа всг1пд) подлежат изменению, а следовательно, они могут ссылаться на другой объект. Но содержимое самого объекта типа вгг109 не меняется после его создания.
Для того чтобы стало понятнее, почему неизменяемые строки не являются помехой, воспользуемся еще одним методом обращения со строками: ВцЬвбг109 () . Этот метод возвращает новую строку, содержащую часть вызывающей строки. В итоге создается новый строковый объект, содержащий выбранную подстроку, тогда как исходная строка не меняется, а следовательно, соблюдается принцип постоянства строк. Ниже приведена рассматриваемая здесь форма метода 80Ьвгг1п9 (): вггьпч ВцЬвсгьпд(1пг индекс начала, ьпт длина) где индекс на чала обозначает начальный индекс исходной строки, а длина — длину выбираемой подстроки.
206 Часть (. язык С№ Ниже приведена программа, в которой принцип постоянства строк демонстрируется на примере использования метода БпЬягг1пд () . // Применить метод ЯпЬвсгдпд(] пвдпд Бувяещ; с1аяя БпЬЯСг ( всагдс чо1б Мадп() ясгдпд огдясг = "В С() упрощается обращение со строками." // сформировать подстроку ясгдпд яоЪясг = огдявг.зпЬясгдпд(5, 20) Сопяо1е.иг1сеъгпе("огдявг: " + огдявг)ь Сопяо1е.нг1ГеЬ1пе("вппвсг: " + япЬвсг)/ Вот к какому результату приводит выполнение этой программы. огдясг: В С() упрощается обращение со строками. впЬясг: упрощается обращение Как видите, исходная строка из переменной огдясг не меняется, а выбранная из нее подстрока содержится в переменной япЬясг. И последнее замечание: несмотря на то, что постоянство строк обычно не является ни ограничением, ни помехой для программирования на С№, иногда оказывается полезно иметь возможность видоизменять строки.
Для этой цели в С№ имеется класс ясгдпдВп11бег, который определен в пространстве имен яуясещ. техс. Этот класс позволяет создавать строковые объекты, которые можно изменять. Но, как правило, в программировании на СФ иснользуегся тип я сг1пд, а не класс Бсгдпднпд1бег. Применение строк е операторах аттз.~сЬ Объекты типа ясг1пд могут использоваться для управления оператором яи1ССЬ. Это единственный нецелочисленный тип данных, который допускается применять в операторе яи1ссь. Благодаря такому применению строк в некоторых сложных ситуациях удается найти более простой выход из положения, чем может показаться на первый взгляд.
Например, в приведенной ниже программе выводятся отдельные цифры, соответствующие словам "один", "два" и "три". Продемонстрировать управление оператором яндвсп посредством строк. пвдпд Яувгещ; с1аяв Ядг1пдзнгвсп ( всасдс тога Мадп М ( яяг1пд() ясгя = ( "один", "два", "три", "два", "один" ); догеасп(вдг1пд я дп яств) ( яндссп(я) ( саве "один": Сопво1е.нг1де (1) ) Глава 7.
Массивы и строки 207 Ьгеак) саве "ява": Сопво1е.нггсе(2); Ьгеак( саве Ег)ви": Сопво1е. Хг1ге (3) ) Ьгеак) ) ) Сопво1е.нггсе11пе()) При выполнении этой программы получается следующий результат. 12321 210 Часть!. язык С(( данным только с помощью строго определенного ряда методов, можно предупредить присваивание неверных значений этим данным, выполняя, например, проверку диапазона представления чисел. Для закрытого члена класса нельзя задать значение непосредственно в коде за пределами класса. Но в то же время можно полностью управлять тем, как и когда данные используются в объекте.
Следовательно, правильно реализованный класс образует некий "черный ящик", которым можно пользоваться, но внутренний механизм его действия закрыт для вмешательства извне. Модификаторы доступа Управление доступом в языке С(( организуется с помощью четырех модификаторов досаупа: рпЫгс, рг1наге, ргогестес( и 1пгегпа1. В этой главе основное внимание уделяется модификаторам доступа рпь11с и р г гна ге. модификатор рго се с тес( применяется только в тех случаях, которые связаны с наследованием, и поэтому речь о нем пойдет в главе 11. А модификатор 1пгегпа1 служит в основном для сборки, которая в широком смысле означает в С(( разворачиваемую программу или библиотеку, и поэтому данный модификатор подробнее рассматривается в главе 16.
Когда член класса обозначается спецификатором рпЬ11с, он становится доступным из любого другого кода в программе, включая и методы, определенные в других классах. Когда же член класса обозначается спецификатором рг1наге, он может быть доступен только другим членам этого класса. Следовательно, методы из других классов не имеют доступа к закрытому члену (рг1насе) данного класса. Как пояснялось в главе 6, если ни один из спецификаторов доступа не указан, член класса считается закрытым для своего класса по умолчанию.
Поэтому при создании закрытых членов класса спецификатор рг1насе указывать для них необязательно. Спецификатор доступа указывается перед остальной частью описания типа отдельного члена. Это означает, что именно с него должен начинаться оператор объявления члена класса. Ниже приведены соответствующие примеры.
роЫгс ясг1пч еггмяч; рггнаге оооЬ1е Ьа1; рггнаге Ьоо1 1яеггог(Ьуге ягагоя( ( Для того чтобы стали более понятными отличия между модификаторами рпЫ1с и рг1нате, рассмотрим следующий пример программы. Отличия между видами доступа рнЬ11с и рггнаое к членам класса. оя1пч Зуясеьи с1аяя МуС1аяя рг1насе 1пс а1рпа; // закрытый доступ, указываемый явно гпг Ьега; закрытый доступ по умолчанию роЫ1с гпс Чапяпа; // откРытый доступ Методы, которым доступны члены а1рпа и Ьеоа данного класса.
// Член класса может иметь доступ к закрытому члену етого же класса. роЬ11с но1О Зесй1рпа(гпс а( ( а1рпа = а; ) Гдова 8. Подробнее о методах н вассах 211 роЬ11с гпс Оеой1рйа() ( гетнгп а1рьа; ) рцьтьс ного-Яесвеса(1пс а) ( Ьепа = а; роЬ11с 1пп Оепвепа() ( гепогп Ьепа) ) о1аяя йссеяяОешо япап1с по1с) Маьп () ( Мус1аяя оЬ = пен МуС1азя () ! // Доступ к членам а1рйа и Ьега данного класса // разрешен только посредством его методов.
оЬ.Яесй1рйа(-99)! оЬ.ЗеГВепа(19): Сопяо1е.ыг1певьпе("оЬ.а1рла равно " + оЬ.Оепй1рьа()) Сопзо1е.нг1сесьпе("оЬ.Ьеса равно " + оЬ.ОеСВеса())) // Следующие виды доступа к членам а1рйа и Ьеса // данного класса не разрешаются. // оЬ.а1рйа = 10) // Ошибка! а1рйа — закрытый член! О оЬ.Ьеса = 9; // Ошибка! Ьепа — закрытый член! // Член Чап1ша данного класса доступен непосредственно, // поскольку он является открытьвп. оЬ.Чапппа = 99; ) ) Как видите, в классе муС1азя член а1рйа указан явно как ргдуаье, член ьеса становится ргьуасе по умолчанию, а член савва указан как рпЬ11с. Таким образом, члены а1рйа и Ьега недоступны непосредственно из кода за пределами данного класса, поскольку они являются закрытыми.
В частности, ими нельзя пользоваться непосредственно в классе Ассе я я Рево. Они доступны только с помощью таких открытых (рпЬ11с) методов, как Яесй1рЬа () и Оесй1рЬа () . Так, если удалить символы комментария в начале следующей строки кода: // оЬ.а1рла =. 10; // Ошибка! а1рйа — закрытый член! то приведенная выше программа не будет скомпилирована из-за нарушения правил доступа. Но несмотря на то, что член а1рба недоступен непосредственно за пределами класса МуС1ая я, свободный доступ к нему организуется с помощью методов, определенных в классе МуС1аяя, как наглядно показывают методы БеСА1рЬа () и Ое сй1рьа ( ) . Это же относится и к члену ьес а. Из всего сказанного выше можно сделать следующий важный вывод: закрытый член может свободно использоваться другими членами этого же класса, но недоступен для кода за пределами своего класса.
212 Часть Е язык С№ Организация закрытого и открытого доступа Правильная организация закрытого и открытого доступа — залог успеха в объектноориентированном программировании. И хотя для этого не существует твердо установленных правил, ниже перечислен ряд общих принципов, которые могут служить в качестве руководства к действию. ° Члены, используемые только в классе, должны быть закрытыми.
° Данные экземпляра, не выходящие за определенные пределы значений, должны быть закрытыми, а при организации доступа к ним с помощью открытых методов следует выполнять проверку диапазона представления чисел. ° Если изменение члена приводит к последствиям, распространяющимся за пределы области действия самого члена, т.е. оказывает влияние на другие аспекты объекта, то этот член должен быть закрытым, а доступ к нему — контролируемым. ° Члены, способные нанести вред объекту, если они используются неправильно, должны быть закрытыми. Доступ к этим членам следует организовать с помощью открытых методов, исключающих неправильное их использование.