1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 26
Текст из файла (страница 26)
Однако элемент M e m b e r F u n c t i o n () для васнов. Он известен как функция-член, представляющая собой набор кода С#, который можетбыть выполнен с помощью ссылки на имя этой функции. Честно говоря, такое определениесмущает даже меня самого, так что лучше рассмотреть, что такое функция, на примерах.Примечание: отличие между статическими и нестатическими функциями крайневажно. Частично эта тема будет раскрыта в данной главе, но более подробно об этомречь пойдет в главе 8, "Методы класса", где будет введен термин метод, очень распрестраненный в объектно-ориентированных языках программирования наподобие С# лобозначения нестатических функций классов.В следующем фрагменте присваиваются значения члену объекта n l n t и члену класш(статическому члену) n S t a t i c I n t :Exampleexampleexample.nlntExample.nStaticIntnew1;= 2;Example();// Создание объекта// И н и ц и а л и з а ц и я ч л е н а с// использованием объекта// И н и ц и а л и з а ц и я ч л е н а с// использованием классаПрактически аналогично в приведенном далее фрагменте происходит обращение (путемвызова) к функциям M e m b e r F u n c t i o n ( ) и C l a s s F u n c t i o n ( ) :Example e x a m p l e = new E x a m p l e ( ) ; // Создание о б ъ е к т аexample.MemberFunction();// Вызов функции-члена// с у к а з а н и е м о б ъ е к т аExample.ClassFunction();// Вызов функции к л а с с а с// указанием класса// Приведенные далее строки не компилируютсяexample.ClassFunction();// Нельзя обращаться к функции// к л а с с а с у к а з а н и е м о б ъ е к т аE x a m p l e .
M e m b e r F u n c t i o n ( ) ; // Нельзя обращаться к функции// члену с у к а з а н и е м к л а с с аОтличие между функциями класса (статическими) и функциями-членами(нестатическими), или методами, отражает различие между переменными класса (статическими) и переменными-членами (нестатическими), описанное ранее!в главе 6, "Объединение данных — классы и массивы".Выражение e x a m p l e . M e m b e r F u n c t i o n ( ) передает управление коду, содержащемуся внутри функции. Процесс вызова E x a m p l e .
C l a s s F u n c t i o n () практически такой же. В результате выполнения приведенного выше фрагмента кода получается слдующий вывод на экран:ЭтоЭтофункция-членфункция классаПосле того как функция завершает свою работу, она передает управление в точкуиз которой она была вызвана.Я включаю круглые скобки при указании функций в т е к с т е — напримеM a i n () — чтобы функции было легче распознать. Без этого упоминания ихв тексте можно легко спутать с переменными или классами.В приведенном примере код функций не делает ничего особенного, кроме вывода на!экран единственной строки, но в общем случае функции выполняют различные сложныеоперации, такие как вычисление математических функций, объединение строк, сортировка массивов или отправка электронных писем, словом, сложность решаемых функциями задач ничем не ограничена.
Функции могут быть любого размера и любой степенисложности, но все же лучше, если они будут небольшими по размеру, так как с такимифункциями гораздо легче работать.142Часть III. Объектно-основанное программированиеВ этом разделе в качестве демонстрации того, как разумное определение функцийможет помочь сделать программу проще для написания и понимания, будет взята монолитная программа C a l c u l a t e l n t e r e s t T a b l e из главы 5, "Управление потоком выполнения", и разделена на несколько функций.
Такой процесс переделки рабочего кодапри сохранении его функциональности называется рефакторингом, и Visual Studio 2005обеспечивает удобное меню Refactor, которое автоматизирует большинство распространенных задач рефакторинга.Определение функций и их вызовы будут детально рассмотрены немного позжев этой главе, а пока считайте данный пример просто кратким обзором.Чтение комментариев при опущенном программном коде должно способствовать пониманию намерений программиста.
Если это не так — значит, вы плохокомментируете ваши программы. (И наоборот, если вы не можете, опустивбольшинство комментариев, понять, что делает программа на основании именфункций, значит, вы недостаточно ясно именуете функции и/или делаете ихслишком большими)."Скелет" программы C a l c u l a t e l n t e r e s t T a b l e выглядит следующим образом:publicstaticvoidMain ( s t r i n g []args){// Приглашение в в е с т и начальный вклад.// Если вклад о т р и ц а т е л е н , г е н е р и р у е т с я сообщение об// о ш и б к е .// Приглашение для ввода процентной с т а в к и .// Если п р о ц е н т н а я с т а в к а о т р и ц а т е л ь н а , г е н е р и р у е т с я// сообщение об ошибке./ / П р и г л а ш е н и е для, в в о д а к о л и ч е с т в а л е т .// Вывод в в е д е н н ы х д а н н ы х ./ / Цикл п о в в е д е н н о м у к о л и ч е с т в у л е т .while(nYear <= n D u r a t i o n ){// В ы ч и с л е н и е з н а ч е н и я в к л а д а с н а ч и с л е н н ы м иIIпроцентами.// Вывод р е з у л ь т а т а в ы ч и с л е н и й .•*.}}Это пример хорошего метода проектирования функций.
Если вы вернетесь и изучитепрограмму, то увидите, что она состоит из следующих трех частей:I / часть начального ввода данных, в которой пользователи вводят вклад, процентную ставку и срок;| / раздел, выводящий введенную информацию на экран, чтобы пользователь могубедиться в корректности ввода;I J последняя часть кода, создающая и выводящая таблицу на экран.Глава 7, Функции функций143Э т о х о р о ш е е н а ч а л о д л я в ы п о л н е н и я р е ф а к т о р и н г а . К р о м е т о г о , е с л и в ы внимателрассмотрите часть ввода начальной и н ф о р м а ц и и , то увидите, что код для вводавклада,процентной ставки исрокап р а к т и ч е с к и о д и н и т о т ж е . Э т о н а б л ю д е н и е д а е т е щ е о д н у т о ч к у д л я рефакторинга.Все п е р е ч и с л е н н о е позволяет в ы п о л н и т ь р е ф а к т о р и н г п р о г р а м м ы CalcllatelnterestTableисоздатьпрограммуCalculatelnterestTableWithFunctions.//CalculateInterestTableWithFunctions////////Генерация таблицы роста вклада по тому же алгоритму, чтои ранее рассматривавшихся программах, однако в этойпрограмме работа распределена между несколькимифункциями.usingSystem;namespace{publicCalculateInterestTableWithFunctionsclassProgram{publics t a t i cvoidMain(string[]args){// Раздел 1 - ввод данных, необходимых для создания// таблицыdddIecimaecimaecimanputllllnm P r i n c i p a l = 0;m l n t e r e s t = 0,m D u r a t i o n = 0;terestData(refmPrincipal,refmlnterest,refmDuration);// Раздел 2 - проверка введенных данных путем вывода// их пользователю на экранConsole.WriteLine();// skip a.lineConsole.WriteLine("ВкладmPrincipal);="+C o n s o l e .
W r i t e L i n e ( " П р о ц е н т н а я ставка = " +mlnterestConsole.WriteLine("Срок+"%") ;="+m D u r a t i o n + . " лет");Console.WriteLine();// Раздел 3 - и, наконец, вывод таблицы вкладов по// годамOutputlnterestTable(mPrincipal,mlnterest,mDuration);// Ожидаем подтверждения пользователяConsole.WriteLine("Нажмите744<Enter>для"+Часть III. Объектно-основанное программирован"завершенияпрограммы...");Console.Read();}////InputlnterestDataпроцентной ставкииклавиатурный вводсрока для расчетавклада,таблицы// Эта функция реализует раздел 1, разбивая его на три// компонентаpublics t a t i cvoidInputlnterestData(refrefref{mPrincipal,mlnterest,mDuration)// la ПолучениевкладаmPrincipal=InputPositiveDecimal("вклад");//Получение16mlnterest//}decimaldecimaldecimal=ставкиInputPositiveDecimal("процентнаяПолучение1вmDurationпроцентной=ставка");срокаInputPositiveDecimal("срок");//InputPositiveDecimal//типа//Выполняется//н е о т р и ц а т е л ь н о с т ьdecimalс-возвращаетположительноечислоклавиатуры.т о л ь к ооднап р о в е р к ав в е д е н н о г о-наз н а ч е н и я .publics t a t i cdecimalInputPositiveDecimal(stringsPrompt){//Цикл//значениевыполняется,поканебудетвведеноверноеwhile(true){// Приглашение для вводаConsole.Write("Введите " +sPrompt+" : " ) ;// Получение значения типа d e c i m a l с клавиатурыstring slnput = Console.ReadLine();decimal mValue = C o n v e r t .
T o D e c i m a l ( s l n p u t ) ;//Выходif(mValue{//изцикла>=Возвратreturnпривводекорректногозначения0)введенногозначенияmValue;}// В п р о т и в н о м с л у ч а е г е н е р и р у е т с я// сообщение об ошибкеConsole.WriteLine(sPrompt+Глава 7. Функции функцийивыводится145" не может иметь о т р и ц а т е л ь н о е з н а ч е н и е " ) ;Console.WriteLine("Попробуйтееще р а з " ) ;Console.WriteLine();}}//////O u t p u t l n t e r e s t T a b l e - для заданных значений вклада,п р о ц е н т н о й с т а в к и и с р о к а г е н е р и р у е т и выводит наэкран таблицу роста вклада// Реализация раздела 3 основной программыpublics t a t i cvoidOutputlnterestTable(decimaldecimaldecimalmPrincipal,mlnterest,mDuration){for(intnYear=1;nYear<=mDuration;nYear++){// Вычисление начисленных процентовdecimalmlnterestPaid;mlnterestPaid = mPrincipal *(mlnterest/100);// Вычисление значения нового вклада путем// добавления начисленных процентов к основному//вкладуmPrincipal = mPrincipal + mlnterestPaid;// Округление вклада до копеекmPrincipal = decimal.Round(mPrincipal,//Вывод р е з у л ь т а т аConsole.WriteLine(nYear}}+"-"+2);mPrincipal);}}Раздел M a i n () разделен на три очевидные части, каждая из которых выделена иментарием с полужирным шрифтом.
Кроме того, первая часть, в свою очередь, поделана три подраздела — 1а, 1 б и 1в.Вам не следует пытаться выделять в своих исходных текстах комментариилужирным шрифтом или номерами разделов. Исходный текст реальной программы и без того сложная и запутанная штука, чтобы вносить в него искуственные усложнения. На практике для понимания достаточно ясных и информтивных имен функций, указывающих их предназначение.В первой части для ввода значений трех переменных, необходимых для работы программы ( m P r i n c i p a l , m l n t e r e s t и м m D u r a t i o n ) , вызывается функция I n p u t l nt e r e s t D a t a ( ) .