1629295403-b876e2087bddebea4bc9666fb2377a02 (846199), страница 56
Текст из файла (страница 56)
Объектно-ориентированное программирова// Снятие со с ч е т а с о с т а в ш е й с яreturn base . Withdraw (mWithdrawal) ;}Вызов b a s e . W i t h d r a w ( )суммойприводит к вызову метода B a n k A c c o u n t . W i t h d r a w ( ) ;и самым п р о б л е м а , с в я з а н н а я с р е к у р с и е й , с н и м а е т с я . К р о м е т о г о , д а н н о е р е ш е н и е работает и при и з м е н е н и и и е р а р х и и н а с л е д о в а н и я .Можно п е р е г р у з и т ь м е т о д б а з о в о г о к л а с с а м е т о д о м в п о д к л а с с е . Э т о и з а м е ч а т е л ь н о ,одновременно о ч е н ь о п а с н о .Проведем м ы с л е н н ы й э к с п е р и м е н т : к о г д а д о л ж н о п р и н и м а т ь с я р е ш е н и е о т о м , к а к о йиз м е т о д о в — B a n k A c c o u n t . W i t h d r a w ()илиS a v i n g s A c c o u n t .
W i t h d r a w ()—будет вызван: во в р е м я к о м п и л я ц и и и л и во в р е м я в ы п о л н е н и я п р о г р а м м ы ?Д л я т о г о ч т о б ы п о н я т ь , в ч е м з д е с ь о т л и ч и е , б у д е т н е м н о г о и з м е н е н а рассматривавшаяся ранеепрограмма H i d i n g W i t h d r a w a l(здесьприведенатолько та часть, в которую внесены изменения).// H i d i n g W i t h d r a w a l P o l y m o r p h i c a l l y сокрытие метода// Withdraw ()б а з о в о г о к л а с с а м е т о д о м с т е м же и м е н е м// п о д к л а с с еpublic c l a s sProgramв(publics t a t i cvoidMakeAWithdrawal(BankAccountba,decimalmAmount){ba.Withdraw(mAmount);}publics t a t i cvoidMain(string[]args){BankAccountba;SavingsAccountsa;ba = new B a n k A c c o u n t ( 2 0 0 M ) ;MakeAWithdrawal(ba,100M);sa = new S a v i n g s A c c o u n t ( 2 0 0 M ,12);MakeAWithdrawal(sa,100M);// Выводим с о с т о я н и я с ч е т о вConsole.WriteLine("БалансBankAccountравен{0:C}",ba.Balance);Console.WriteLine("БалансSavingsAccountравен{0:C}",sa.Balance);// Ожидаем п о д т в е р ж д е н и я п о л ь з о в а т е л яConsole.WriteLine("Нажмите <Enter> для " +"завершения программы...");Console.Read();Вывод этой д е м о н с т р а ц и о н н о й п р о г р а м м ы на э к р а н м о ж е т вас удивить (а м о ж е т и неудивить — в з а в и с и м о с т и от т о г о , ч е г о и м е н н о вы о ж и д а л и ) :Глава 13.
Полиморфизм291БалансBankAccountБалансSavingsAccountНажмите<Enter>равендля$100.00равен$100.00завершенияпрограммы...В э т о т р а з , в м е с т о с н я т и я с о с ч е т а в ф у н к ц и и M a i n ( ) , п р о г р а м м а п е р е д а е т объектсчета функции M a k e A W i t h d r a w a lПервыйобъектcount?вопросочевиден:SavingsAccount,Ответне().какеслименее ясен:функцияонаM a k e A W i t h d r a w a l ()ожидаетпотомучтовкачествеможетаргументаSavingsAccountприниматьобъектЯВЛЯЕТСЯBankAcBankAcc o u n t ( с м . г л а в у 12, " Н а с л е д о в а н и е " ) .Второй вопрос не так очевиден.
Когда функции M a k e A W i t h d r a w a l ()объект B a n k A c c o u n t , она вызывает B a n k A c c o u n t . W i t h d r a w ()передает!— э т о понятно. Н ек о г д а п е р е д а е т с я о б ъ е к т т и п а S a v i n g s A c c o u n t , в ы з ы в а е т с я т о т ж е м е т о д .
Должен л ив этом случае вызываться метод W i t h d r a w ()Содной стороны,b a . W i t h d r a w ()поскольку объект baподкласса?п р и н а д л е ж и т т и п у B a n k A c c o u n t , вызовд о л ж е н в ы з ы в а т ь м е т о д B a n k A c c o u n t . W i t h d r a w ( ) . С другой стор о н ы , х о т я о б ъ е к т b a и о б ъ я в л е н к а к B a n k A c c o u n t , ф а к т и ч е с к и о н п р е д с т а в л я е т собойобъектSavingsAccount,такчтодолженбытьвызванметодSavingsAcc o u n t . W i t h d r a w ( ) . Оба аргумента достаточно логичны.В д а н н о м с л у ч а е С # п р и н и м а е т к а к б о л е е в е с о м ы й п е р в ы й а р г у м е н т .
Э т о б о л е е безоп а с н ы й в ы б о р — р а б о т а т ь с о б ъ я в л е н н ы м т и п о м — п о с к о л ь к у он у с т р а н я е т все недоразумения. Объект объявлен как B a n k A c c o u n t , и так тому и быть.Что неверно в стратегии использования объявленного типаВ р я д е с л у ч а е в в а м не т р е б у е т с я р а б о т а с о б ъ я в л е н н ы м т и п о м . На с а м о м д е л е необх о д и м о , ч т о б ы в ы з о в б а з и р о в а л с я на реальном типе,т.е.на т и п е в р е м е н и исполнения,а н е н а о б ъ я в л е н н о м т и п е .
Н а п р и м е р , в а м н у ж н о , ч т о б ы в ы п о л н я л и с ь д е й с т в и я с о счетомт и п а S a v i n g s A c c o u n t , к о т о р ы й х р а н и т с я в п е р е м е н н о й т и п а B a n k A c c o u n t . Такаяв о з м о ж н о с т ь п р и н я т и я р е ш е н и я в о в р е м я в ы п о л н е н и я п р о г р а м м ы н а з ы в а е т с я полиморфизмом,илипозднимсвязываниемт и п а н а з ы в а е т с я раннимТермин(lateсвязываниемполиморфизмbinding).Стратегия(early b i n d i n g ) ,происходитизвиспользованияпротивоположностьгреческогоязыка:полиобъявленногопозднему.означаетмного,а морф — ф о р м а , и л и д е й с т в и е .П о л и м о р ф и з м и п о з д н е е с в я з ы в а н и е в о о б щ е - т о не о д н о и то ж е .
О д н а к о их отличиев е с ь м а т о н к о е . Полиморфизм о з н а ч а е т в о з м о ж н о с т ь п р и н я т и я р е ш е н и я о т о м , какой мет о д д о л ж е н б ы т ь в ы з в а н в п р о ц е с с е в ы п о л н е н и я п р о г р а м м ы . Позднее связывание — способ реализации полиморфизма языком программирования.П о л и м о р ф и з м я в л я е т с я к л ю ч е в о й с о с т а в л я ю щ е й ч а с т ь ю объектно-ориентированногоп р о г р а м м и р о в а н и я . О н н а с т о л ь к о в а ж е н , ч т о я з ы к и , е г о н е п о д д е р ж и в а ю щ и е , н е имеютправа называться объектно-ориентированными.Я з ы к и п р о г р а м м и р о в а н и я , п о д д е р ж и в а ю щ и е к л а с с ы , н о н е поддерживающиеполиморфизм,называютсяобъектно-основаннымиязыками(object-basedlanguages). П р и м е р о м такого я з ы к а м о ж е т служить я з ы к Ada.292Часть IV. Объектно-ориентированное программированиеБез п о л и м о р ф и з м а в н а с л е д о в а н и и м а л о т о л к у .
П о з в о л ь т е п р и в е с т и н а г л я д н ы й пример, и л л ю с т р и р у ю щ и й д а н н ы й т е з и с . П р е д п о л о ж и м , вы н а п и с а л и м о щ н у ю п р о г р а м м у ,использующую к л а с с . . . ну, с к а ж е м , S t u d e n t . П о с л е н е с к о л ь к и х м е с я ц е в п р о е к т и р о в а ния, кодирования и т е с т и р о в а н и я вы н а к о н е ц - т о в ы н е с л и ее на суд в о с х и щ е н н ы х пользователей ( н а ч и н а ю щ и х д а ж е п о г о в а р и в а т ь , ч т о с о в е р ш е н н о н а п р а с н о н е с у щ е с т в у е т Н о бевскойпремии в области программирования).Проходит время, и в а ш ш е ф требует, ч т о б ы вы д о б а в и л и в п р о г р а м м у в о з м о ж н о с т ь работы с аспирантами, к о т о р ы е , к о н е ч н о , п о х о ж и на студентов, но все же н е м н о г о о т л и ч а ю т с я отних (сами аспиранты считают, что о н и о т л и ч а ю т с я во в с е м ) .
П р е д п о л о ж и м , что ф о р м у л ы длявычисления оплаты за обучение для студентов и аспирантов с о в е р ш е н н о р а з л и ч н ы . В а ш е м убоссу это безразлично, но в п р о г р а м м е имеется м а с с а в ы з о в о в ф у н к ц и и C a l c T u i t i o n ( ) ,яредаазначенной для таких расчетов. В о т п р и м е р о д н о г о из таких в ы з о в о в :void S o m e F u n c t i o n ( S t u d e n ts){// . .. Какие-тоs. C a l c T u i t i o n ( ) ;II... продолжение .
. .}действия...Если б ы С # н е п о д д е р ж и в а л п о з д н е е с в я з ы в а н и е , т о в а м б ы п р и ш л о с ь р е д а к т и р о в а т ьфункцию S o m e F u n c t i o n ( ) , ч т о б ы п р о в е р я т ь в н е й , я в л я е т с я ли п е р е д а н н ы й о б ъ е к т s переменной типа S t u d e n t и л и G r a d u a t e S t u d e n t . П р о г р а м м а д о л ж н а б ы л а б ы в ы з ы в а т ьStudent. C a l c T u i t i o n ( )в случае, к о г д а п е р е м е н н а я s п р и н а д л е ж а л а б ы к л а с с у S t u -|dent, и G r a d u a t e S t u d e n t . C a l c T u i t i o n ( ) в случае к л а с с а G r a d u a t e S t u d e n t .Это было б ы н е т а к с т р а ш н о , е с л и б ы н е д в е в е щ и .Это т о л ь к о о д н а ф у н к ц и я .
А т е п е р ь п р е д с т а в ь т е , ч т о C a l c T u i t i o n ( )вызывается в с о т н я х м е с т . . .Предположим, чтоC a l c T u i t i o n () — не единственное отличие между двумяклассами. Ш а н с ы , что вы найдете все места в п р о г р а м м е , т р е б у ю щ и е и з м е н е н и й ,резко с н и ж а ю т с я . . .При п о д д е р ж к е п о л и м о р ф и з м а в ы п р о с т о п о з в о л я е т е С # с а м о с т о я т е л ь н о р е ш и т ь , какой метод д о л ж е н б ы т ь в ы з в а н .Использование i s д л я полиморфного доступак скрытому методуКаким о б р а з о м с д е л а т ь п р о г р а м м у п о л и м о р ф н о й ? О д и н и з п о д х о д о в д л я р е ш е н и яэтой задачи в С# с о с т о и т в и с п о л ь з о в а н и и к л ю ч е в о г о с л о в а i s (о к о т о р о м р а с с к а з ы в а юсь в главе 12,"Наследование").ВыражениеbaisSavingsAccountвозвращаетиачение t r u e и л и f a l s e в з а в и с и м о с т и о т к л а с с а о б ъ е к т а в о в р е м я в ы п о л н е н и я программы.
О б ъ я в л е н н ы й т и п м о ж е т б ы т ь B a n k A c c o u n t , н о с к а к о г о т и п а о б ъ е к т о м приходится и м е т ь д е л о в р е а л ь н о с т и ? В п р и в е д е н н о м д а л е е ф р а г м е н т е и с х о д н о г о т е к с т а i sиспользуется д л я о б р а щ е н и я к ф у н к ц и и W i t h d r a w ( )publicpublicclassкласса S a v i n g s A c c o u n t .Programs t a t i cvoidMakeAWithdrawal(BankAccountdecimalГлава 13. Полиморфизмba,mAmount)293{ifbaisSavingsAccount{SavingsAccountsa=(SavingsAccount)ba,•sa.Withdraw(mAmount);}else{ba.Withdraw(mAmount);}}Теперь, когда M a i n () передает функции объект типа S a v i n g s A c c o u n t , функцииM a k e A W i t h d r a w a l ()функциюпроверяет типвременивыполненияобъекта baи вызываетSavingsAccount.Withdraw().Программист может выполнить вызов одной строкой:((SavingsAccount)ba).Withdraw(mAmount);Об э т о м у п о м и н а е т с я т о л ь к о п о т о м у , ч т о и м е е т с я м а с с а п р о г р а м м , в которыйв ы з о в ы о с у щ е с т в л я ю т с я и м е н н о т а к и м о б р а з о м .
О д н а к о д а н н ы й подход привод и т к м е н е е у д о б о ч и т а е м о м у и с х о д н о м у т е к с т у , с о о т в е т с т в е н н о — к большемуколичеству ошибок в программе.П о д х о д с и с п о л ь з о в а н и е м i s в п о л н е р а б о т о с п о с о б е н , но э т о д а л е к о не лучшая идеяПрименение is требует от функции M a k e A W i t h d r a w a l ()осведомленности о всехв о з м о ж н ы х т и п а х с ч е т о в , к о т о р ы е и м е ю т с я (и м о г у т п о я в и т ь с я в д а л ь н е й ш е м ) в банкЭто накладывает на функцию M a k e A W i t h d r a w a l ()с л и ш к о м б о л ь ш у ю ответствен о с т ь .