Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Books / 3_C#_2005_для_чайников_(Дэвис-2008)

.pdf
Скачиваний:
86
Добавлен:
24.03.2015
Размер:
15.46 Mб
Скачать

Окончание табл. 9.1

Все эти модификаторы могут показаться слишком запутанными, но вы все­ гда можете получить информацию о них в справочной системе С#. Чтобы увидеть модификаторы в действии, взгляните на приведенную далее демон­ страционную программу OutputFormatControls, позволяющую ввести не только число с плавающей точкой, но и модификатор формата, который будет использован при выводе введенного числа обратно на экран.

//OutputFormatControls - позволяет пользователю посмотреть , // как влияют модификаторы форматирования на вывод чисел . //Модификаторы вводятся в программу так ж е , как и числа — в // процессе работы программы

namespace OutputFormatControls

{

using System;

public class Program

{

public static void M a i n (string [] args)

{

//

Бесконечный

цикл для

ввода чисел, пока пользователь

//

не введет вместо числа пустую строку, что является

//

сигналом к

окончанию

работы программы

for(;;)

{

// Ввод числа и выход из цикла, если введена пустая]

//строка

Console . W r i t e L i n e ( "Введите число с плавающей точкой") string sNumber = C o n s o l e . R e a d L i n e О ;

if (sNumber.Length == 0)

{

b r e a k ;

}

double dNumber = D o u b l e . P a r s e ( s N u m b e r ) ;

//Ввод модификаторов форматирования, разделенных

//пробелами

Console . WriteLine("Введите модификаторы " +

 

 

"форматирования, разделенные " + ,

 

 

" п р о б е л а м и " ) ;

chart]

separator =

{'

' } ;

string

sFormatString

=

C o n s o l e . R e a d L i n e ( ) ;

string[] sFormats

=

sFormatString . Split(separator) ;

//Цикл по введенным модификаторам

foreach(string s in sFormats)

{

if (s.Length != 0)

{

//Создание управляющего элемента форматирования!

//из введенного модификатора

string sFormatCommand = " {0 : " + s + " } " ;

//Вывод числа с применением созданного

//управляющего элемента форматирования Console . Write(

 

"Модификатор

{ о }

дает ", sFormatCommand);

 

try

 

 

 

{

 

 

 

Console . WriteLine(sFormatCommand, d N u m b e r ) ;

 

}

 

 

 

catch(Exception)

 

 

 

{

 

 

 

Console . WriteLine("<Неверный м о д и ф и к а т о р > " ) ;

 

}

 

 

 

C o n s o l e . W r i t e L i n e ( ) ;

 

 

}

 

 

}

}

 

 

 

 

 

//

Ожидаем подтверждения

пользователя

Console . WriteLine("Нажмите <Enter> для " +

 

"завершения п р о г р а м м ы . . . " ) ;

C o n s o l e . R e a d ( ) ;

 

 

}

 

 

 

}

 

 

 

}

 

 

 

220

Часть

III.

Объектно-основанное программировал

Программа OutputFormatControls считывает вводимые пользователем числа сплавающей точкой в переменную dNumber до тех пор, пока не будет введена пустая прока — это является признаком окончания ввода. Обратите внимание, что программа не выполняет никаких тестов для проверки корректности введенного числа с плавающей точкой. Программа считает пользователя достаточно интеллектуальным и знающим, как выглядят числа с плавающей точкой (довольно смелое допущение!).

Затем программа считывает ряд модификаторов форматирования, разделенных про­ белами. Каждый из них далее комбинируется со строкой { 0 } в переменной sFormat ­ Command. Например, если вы ввели N4, программа создаст управляющий элемент

{0: N4}. После чего введенное пользователем число выводится на экран с применением этого элемента:

Console.WriteLine (sFormatCommand, dNumber) ;

В рассмотренном только что случае модификатора N4 команда по сути превращается в tasole. WriteLine (" {О :N4 }" , dNumber) ;

жа ъытлядит типичный вывод программы на экран (полужирным шрифтом вы-

; делен ввод пользователя):

 

 

.Введите число с плавающей точкой

 

 

1234 5 . 6 7 8 9

 

 

 

Введите модификаторы форматирования,

разделенные

пробелами

СЕ F1 N0 0000000 .00000

 

 

Кодификатор {0:С} дает $ 12,345 . 68

 

 

Кодификатор {0:Е} дает 1.234568Е+004

 

 

Кодификатор

{ 0 : F1} дает 12345 . 7

 

 

Кодификатор

{0:N0} дает 12,346

 

 

одификатор {0:0000000.00000} дает 0012345 . 67890

 

Введите число с плавающей точкой

 

 

.12345

 

 

 

Заедите модификаторы форматирования,

разделенные

пробелами

ео.о%

Кодификатор {0:00.0%} дает 1 2 . 3 % Идите число с плавающей точкой

Заште <Enter> для завершения программы ...

Будучи примененным к числу 12345.6789, модификатор N0 добавляет в нужное место пятую (часть N) и убирает все цифры после десятичной точки (часть 0), что дает стро­ ки, 346 (последняя цифра — результат округления, а не отбрасывания).

Аналогично, будучи примененным к числу 0.12345, модификатор 0 0.0% даст 12.31 Знак % приводит к умножению числа на 100 и добавлению символа % к выводи- иу числу. 00.0 указывает, что в выводимой строке должно быть по меньшей мере две фы слева от десятичной точки, и только одна — справа. Если тот же модификатор применить к числу 0.01, будет выведена строка 01.0%.

Непонятная конструкция try . . . catch предназначена для перехвата всех по­ тенциальных ошибок при вводе некорректных чисел. Однако об этом расска­ зывается совсем в другой главе.

[ и з 9. Работа со строками в С#

221

Часть IV

Объектно-ориентированное программирование

Объектно-ориентированное программирование — термин, вызывающий у программистов наибольший выброс адреналина в кровь. Так, объ­ ектно-ориентированным языком программирования является С++ — и в этом его главное отличие от старого доброго С. К объектноориентированным языкам определенно относится и Java, как и еще добрая сотня языков, придуманных за последний десяток лет. Но что же это такое — объектно-ориентированный! Зачем это надо? и надо ли вообще? стоит ли использовать это в своих программах?

В этой части вы столкнетесь с возможностями С#, которые делают

его объектно-ориентированным языком программирования. Объект­ но-ориентированное программирование — это не просто работа с объектами; это — мощь и гибкость программ при меньших затра­ чиваемых усилиях, это элегантность проекта, словом — это все, из­ ложенное в данной части книги.

Глава 10

Что такое объектно-ориентированное программирование

>Основы объектно-ориентированного программирования

>Абстракция и классификация

>Важность объектно-ориентированного программирования

этой главе будут даны ответы на два основных вопроса — какие концепции ле­ жат в основе объектно-ориентированного программирования и чем они отлича­

ются от уже рассмотренных концепций функционального программирования.

Когда мы с сыном смотрим футбол, я подчас испытываю непреодолимую тягу к вред­ ным для здоровья, но таким вкусным кулинарным изыскам, в частности, к мексиканским блюдам. Достаточно бросить на тарелку чипсы, бобы, сыр, приправы и пять минут зажа­ ривать эту массу в микроволновой печи.

Для того чтобы воспользоваться печью, следует открыть ее дверцу, поместить внутрь полуфабрикат и нажать несколько кнопок на передней панели. Через пару минут блюдо готово (только не стойте перед печью, а то ваши глаза начнут светиться в темноте).

Обратите внимание на то, чего не делалось при использовании микроволновой печи.

Ничего не переключалось и не изменялось внутри печи. Чтобы установить для нее рабочий режим, существует интерфейс — лицевая панель с кнопками и неболь­ шой индикатор времени; это все, что нужно.

Не перепрограммировался процессор внутри печи, даже если прошлый раз гото­ вилось абсолютно другое блюдо.

Не было необходимости смотреть внутрь печи.

При приготовлении блюд не надо было беспокоиться о внутреннем устройстве пе­ чи — даже если вы работаете главным инженером по производству таких печей.

Это не просто пространные рассуждения. В повседневной жизни нас постоянно преследуют стрессы. Чтобы уменьшить их число, мы начинаем обращать внима ние только на события определенного масштаба. В объектно-ориентированно) программировании уровень детализации, на котором вы работаете, называете уровнем абстракции. И объяснить этот термин можно на примере абстрагирот ния от подробностей внутреннего устройства микроволновой печи.

К счастью, ученые-кибернетики открыли объектную ориентированность и ряд других концепций, снижающих уровень сложности, с которым должен работать программно Использование абстракций делает программирование более простым и уменьшает коли чество возможных ошибок. Именно в этом направлении как минимум полстолетия да жется прогресс в программировании— работа со все более сложными концепциями а все меньшим количеством ошибок.

Во время приготовления блюда многие смотрят на микроволновую печь просто как на железный ящик. И пока ею можно управлять с помощью интерфейса, ее нельзя сло­ мать, "подвесить" или, что еще хуже, превратить готовящееся блюдо в угли.

Приготовление блюд с помощью функций

Представьте себе, что я попросил бы своего сына написать алгоритм приготовлен! мною закусок. Поняв наконец, чего я от него добиваюсь, он бы, наверное, написал что-то вроде "открыть банку бобов, натереть сыр, посыпать перцем" и т.д. Когда дело дошло бы непосредственно до приготовления в печи, он в лучшем случае написал бы нечто тип "готовить в микроволновой печи не более пяти минут".

Этот рецепт прост и верен. Но с помощью подобного алгоритма "функциональный" про граммист не сможет написать программу приготовления закусок. Программисты, работаю щие с функциями, живут в мире, лишенном таких объектов, как микроволновая печь и прочи удобства. Они заботятся о последовательности операций в функциях. В "функциональном" решении проблемы закусок управление будет передано от пальцев рук кнопкам передней па­ нели, а затем внутрь печи. После этого программе придется решать, какое время должна работать печь и когда следует включить звуковой сигнал готовности.

При таком подходе очень трудно отвлечься от сложностей внутреннего устройств! печи. В этом мире нет объектов, за которые можно спрятать всю присущую микроволно­ вой печи сложность.

Приготовление "объектно-ориентированных" блюд

Применяя объектно-ориентированный подход к приготовлению блюд, я первым де­ лом определяю объекты, используемые в задаче: сыр, бобы, чипсы и микроволновая печь. После этого я начинаю моделировать их в программе, не задумываясь над деталя ми их применения.

При этом я работаю (и думаю) на уровне базовых объектов. Главное, думать о том, что приготовить блюдо, не волнуясь о деталях работы микроволновой печи — над этим уже подумали ее создатели (которым абсолютно нет дела до ваших кулинарных пристрастий).

После создания и проверки всех необходимых объектов можно переключиться на следующий уровень абстракции, т.е. мыслить на уровне процесса приготовления закуски не отвлекаясь на отдельные куски сыра или банку бобов. При таком подходе я легко пе­ реведу рецепт моего сына на язык С#.

226

Часть

IV.

Объектно-ориентированное программировании]

В концепции уровней абстракции очень важной частью является классификация. Опять-таки, если бы я спросил моего сына: "Что такое микроволновая печь?" — он бы наверняка ответил: "Это печь, которая...". Если бы затем последовал вопрос: "А что та­ кое печь?" — он бы ответил что-то вроде: "Ну, это кухонный прибор, который...". (При попытке выяснить у него, что же такое кухонный прибор, он наверняка бы спросил, сколько можно задавать дурацких вопросов.)

Из детских ответов становится ясно, что ими печь воспринимается как один из экзем­ пляров вещей, называемых микроволновыми печами. Кроме того, печь является подраз­ делом духовок, а духовки относятся к типу кухонных приборов.

В объектно-ориентированном программировании конкретная микроволновая печь является экземпляром класса микроволновых печей. Класс микроволно­ вых печей является подклассом печей, который, в свою очередь, является под­ классом кухонных приборов.

Люди склонны заниматься классификацией. Все вокруг увешано ярлыками. Мы дела­ ем все для того, чтобы уменьшить количество вещей, которые надо запомнить. Вспом­ ните, например, когда вы первый раз увидели "Пежо" или "Рено". Возможно, в рекламе и говорилось, что это суперавтомобиль, но мы-то с вами знаем, что это не так. Это ведь просто машина. Она имеет все свойства, которыми обладает автомобиль. У нее есть руль, колеса, сиденья, мотор, тормоза и т.д. И можно поспорить, что многие водили бы такую штуку без всяких инструкций.

Но не будем тратить место в книге на описание того, чем этот автомобиль похож на другие. Следует знать лишь то, что это "машина, которая...", и то, чем она отличается от других машин (например, ценой). Теперь можно двигаться дальше. Легковые автомоби­ ли являются таким же подклассом колесных транспортных средств, как грузовики и пи­ капы. При этом колесные транспортные средства входят в состав транспортных средств наравне с кораблями и самолетами.

Зачем вообще нужна эта классификация, это объектно-ориентированное программи­ рование? Ведь оно влечет за собой массу трудностей. Тем более, что уже имеется гото­ вый механизм функций. Зачем же что-то менять?

Иногда может показаться, что легче разработать и создать микроволновую печь спе­ циально для какого-то блюда и не строить универсальный прибор на все случаи жизни. Тогда на лицевую панель не нужно было бы помещать никаких кнопок, кроме кнопки

СТАРТ. Блюдо всегда готовилось бы одинаковое время, и можно было бы избавиться от всех этих бесполезных кнопок типа РАЗМОРОЗКА или Т Е М П Е Р А Т У Р А П Р И Г О Т О В ­ ЛЕНИЯ. Все, что требовалось бы от такой печи, — это чтобы в нее помещалась одна та­

релка с полуфабрикатом. Да, но что же тогда получится? Ведь при этом кубический фут пространства использовался бы для приготовления всего одной тарелки закуски!

Чтобы сэкономить место, можно освободиться от этой глупой концепции — "микрон] новая печь". Для приготовления закуски хватит и внутренностей печи. Тогда в инструкции достаточно написать примерно следующее: "Поместите полуфабрикат в ящик. Соедини красный и черный провод. Установите на трубе излучателя напряжение в 3000 вольт. Дол появиться негромкий гул. Постарайтесь не стоять близко к установке, если хотите иметь ц тей". Простая и понятная инструкция!

Но такой функциональный подход создает некоторые проблемы.

Слишком сложно. Нежелательно, чтобы фрагменты микроволновой печи па мешивались с фрагментами закуски при разработке программы. Но поскольку ц данном подходе нельзя создавать объекты и упрощать написание, работая с и цым из них в отдельности, приходится держать в голове все нюансы каждого of екта одновременно.

Не гибко. Когда-нибудь потребуется замена имеющейся микроволновой печщ печь другого типа. Это делается без проблем, если интерфейс печи можно буд оставить старым. Без четко очерченных областей действия, а также без разделен интерфейса и внутреннего содержимого становится крайне трудно убрать стар объект и поставить на его место новый.

Невозможно использовать повторно. Печи предназначены для приготовлен! разных блюд. Вряд ли кому-то захочется создавать новую печь всякий раз при а обходимости приготовить новое блюдо. Если задача уже решена, неплохо исши зовать ее решение и в других программах.

Объект должен быть способен спроектировать внешний интерфейс максимально прс стым при полной достаточности для корректного функционирования. Если интерфа" устройства будет недостаточен, все кончится битьем кулаком или чем-то более тяжела по верхней панели такого устройства или просто разборкой для того, чтобы добраться» его внутренностей (что наверняка окажется нарушением законодательства об интелла туальной собственности). С другой стороны, если интерфейс слишком сложен, весы сомнительно, что кто-то купит такое устройство (как минимум, вряд ли кто-то будет HI пользовать все предоставляемые интерфейсом возможности).

Люди постоянно жалуются на сложность видеомагнитофонов (впрочем, с переходо на управление с помощью экрана количество жалоб несколько уменьшилось). В эк устройствах слишком много кнопок с различными функциями. Зачастую одна и та i кнопка выполняет разные функции — в зависимости от того, в каком именно состояш находится в этот момент видеомагнитофон. Кроме того, похоже, невозможно найти я видеомагнитофона различных марок с одинаковым интерфейсом.

Теперь рассмотрим ситуацию с автомобилями. Вряд ли можно сказать (и доказать что автомобиль проще видеомагнитофона. Однако, похоже, люди не испытывают тан трудностей с его вождением, как с управлением видеомагнитофоном.

В каждом автомобиле в наличии примерно одни и те же элементы управления и гаи ти на одних и тех же местах. Если же управление отличается... Ну вот вам реальная ж тория из моей жизни — у моей сестры был французский автомобиль, в котором упращ

228

Часть

IV.

Объектно-ориентированное

программирован

ние фарами оказалось там, где у всех "нормальных" автомобилей находится управление сигналами поворота. Отличие вроде бы небольшое, но я так и не научился поворачивать на этом автомобиле влево, не выключив при этом фары...

Кроме того, при хорошо продуманном дизайне автомобиля один и тот же элемент управления никогда не будет использоваться для выполнения более одной операции в за­ висимости от состояния автомобиля.

Микроволновая печь должна быть сконструирована таким образом, чтобы никакая комбинация кнопок или рукояток не могла ее сломать или навредить вам. Конечно, оп­ ределенные комбинации не будут выполнять никаких функций, но главное, чтобы ни од­ на из них не привела к следующему.

Поломке устройства. Какие бы рукоятки ни крутил ваш ребенок и какие бы кнопки не нажимал — микроволновая печь не должна от этого сломаться. После того как вы вернете все элементы управления в корректное состояние, она должна нормально работать.

К пожару или прочей порче имущества или нанесению вреда здоровью по­ требителя. Мы живем в сутяжном мире, и если бы что-то похожее могло про­ изойти — компании пришлось бы продать все вплоть до автомобиля ее президен­ та, чтобы рассчитаться с подающими на нее в суд и адвокатами.

Однако чтобы эти два правила выполнялись, вы должны принять на себя определен­ ную ответственность. Вы ни в коем случае не должны вносить изменения в устройство, в частности, отключать блокировки.

Почти все кухонное оборудование любой степени сложности, включая микроволно­ вые печи, имеет пломбы, препятствующие проникновению пользователя внутрь. Если такая пломба повреждена, это указывает, что крышка устройства была снята, и вся от­ ветственность с производителя тем самым снимается. Если вы каким-либо образом из­ менили внутреннее устройство печи, вы сами несете ответственность за все последую­ щие неприятности, которые могут произойти.

Аналогично, класс должен иметь возможность контролировать доступ к своим членамданным. Никакая последовательность вызовов членов класса не должна приводить программу к аварийному завершению, однако класс не в состоянии гарантировать это, если внешние объекты имеют доступ к внутреннему состоянию класса. Класс должен иметь возможность прятать критические члены-данные и делать их недоступными для внешнего мира.

Итак, как же С# реализует объектно-ориентированное программирование? Впрочем, это не совсем корректный вопрос. С# является объектно-ориентированным языком про-

Глава 10. Что такое объектно-ориентированное программирование

229