ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 3219

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

p u b l i c s t a t i c v o i d M a i n ( s t r i n g [ ]

a r g s )

{

U r C l a s s . A F u n c t i o n ( ) ; / / / / В ы з о в ф у н к ц и и - ч л е н а M y C l a s s m c O b j e c t = n e w m c O b j e c t . A M e t h o d ( ) ;

В ы з о в с т а т и ч е с к о й ф у н к ц и и M y C l a s s . A M e t h o d ( )

M y C l a s s ( ) ;

Имя класса является частью расширенного имени функции, так что для С# очевидно, какую именно функцию A F u n c t i o n () или метод A M e t h o d () вызывать в каждом кон­ кретном случае.

Сокрытие метода базового класса

Итак, метод одного класса может перегружать другой метод того же класса, если ис­ пользует другие аргументы. Метод также может перегружать метод базового класса. Пе­ регрузка метода базового класса известна как сокрытие метода.

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

При использовании функционального подхода вы можете реализовать эту политику посредством переменной-флага в классе, который бы указывал, принадлежит ли объект типу 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 . В этом случае метод снятия со счета дол­ га проверять значение флага, чтобы выяснить, следует ли снимать дополнительные

.50, как показано в следующем фрагменте исходного текста,

public c l a s s B a n k A c c o u n t

{

p r i v a t e d e c i m a l m B a l a n c e ;

p r i v a t e b o o l i s S a v i n g s A c c o u n t ;

/ /

Н а ч а л ь н ы й б а л а н с и ф л а г , у к а з ы в а ю щ и й , я в л я е т с я л и с ч е т

/ /

д е п о з и т н ы м и л и н е т

p u b l i c B a n k A c c o u n t ( d e c i m a l m l n i t i a l B a l a n c e ,

b o o l i s S a v i n g s A c c o u n t )

{

m B a l a n c e = m l n i t i a l B a l a n c e ;

t h i s . i s S a v i n g s A c c o u n t = i s S a v i n g s A c c o u n t ;

)

p u b l i c d e c i m a l W i t h d r a w ( d e c i m a l m A m o u n t )

{

// Е с л и с ч е т д е п о з и т н ы й . . .

i f

( i s S a v i n g s A c c o u n t )

{

 

 

/ / . . . с н и м а е м л и ш н и е 1 . 5 0

 

m B a l a n c e - = 1 . 50М, -

}

/ / Д а л е е о б ы ч н ы й к о д i f ( m A m o u n t T o W i t h d r a w

с н я т и я с о с ч е т а

>m B a l a n c e )

{

m A m o u n t T o W i t h d r a w = m B a l a n c e ;

Глава 13. Полиморфизм

285


m B a l a n c e - = m A m o u n t T o W i t h d r a w ;

r e t u r n m A m o u n t T o W i t h d r a w ;

}

}

c l a s s M y C l a s s

{

p u b l i c v o i d S o m e F u n c t i o n ( )

{

/ / С о з д а е м д е п о з и т н ы й с ч е т

B a n k A c c o u n t b a = n e w B a n k A c c o u n t ( 0 , t r u e ) ;

}

.}

В а ш а функция должна указывать, какой именно счет создается, путем передачи полнительного аргумента конструктору B a n k A c c o u n t . Конструктор сохраняет файл затем используемый в методе W i t h d r a w () Для снятия дополнительной суммы 1.50.

Объектно - ориентированный подход скрывает метод W i t h d r a w () базом го класса B a n k A c c o u n t н о в ы м методом с тем же и м е н е м в классе Sat i n g s A c o o u n t , как показано в приведенной далее демонстрационной программе .

/ /

H i d i n g W i t h d r a w a l

/ /

м е т о д о м п о д к л а с с а

u s i n g S y s t e m ;

- с о к р ы т и е м е т о д а б а з о в о г о к л а с с а с т е м ж е и м е н е м

n a m e s p a c e H i d i n g W i t h d r a w a l

{

/ / B a n k A c c o u n t p u b l i c c l a s s

{

- б а з о в ы й б а н к о в с к и й с ч е т B a n k A c c o u n t

p r o t e c t e d d e c i m a l m B a l a n c e ;

p u b l i c

B a n k A c c o u n t ( d e c i m a l m l n i t i a l B a l a n c e )

m B a l a n c e = m l n i t i a l B a l a n c e ;

p u b l i c

d e c i m a l B a l a n c e

g e t { r e t u r n m B a l a n c e ; }

p u b l i c d e c i m a l W i t h d r a w ( d e c i m a l m A m o u n t )

d e c i m a l m A m o u n t T o W i t h d r a w = m A m o u n t ; i f ( m A m o u n t T o W i t h d r a w > B a l a n c e )

{

m A m o u n t T o W i t h d r a w = B a l a n c e ;

}

m B a l a n c e - = m A m o u n t T o W i t h d r a w ; r e t u r n m A m o u n t T o W i t h d r a w ;

286

Часть IV. Объектно-ориентированное программирован®


// S a v i n g s A c c o u n t - б а н к о в с к и й с ч е т с н а ч и с л е н и е м // п р о ц е н т о в

p u b l i c c l a s s 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

{

p u b l i c d e c i m a l m l n t e r e s t R a t e ;

/ / S a v i n g s A c c o u n t - п р о ц е н т н а я с т а в к а п е р е д а е т с я к а к // ч и с л о от 0 до 10 0

p u b l i c S a v i n g s A c c o u n t ( d e c i m a l m l n i t i a l B a l a n c e , d e c i m a l m l n t e r e s t R a t e )

:b a s e ( m l n i t i a l B a l a n c e )

{

t h i s . m l n t e r e s t R a t e = m l n t e r e s t R a t e / 1 0 0 ;

/ / A c c u m u l a t e l n t e r e s t - н а ч и с л е н и е п р о ц е н т о в p u b l i c v o i d A c c u m u l a t e l n t e r e s t ( )

{

m B a l a n c e = B a l a n c e + ( B a l a n c e * m l n t e r e s t R a t e ) ;

/ / W i t h d r a w

-

с о с ч е т а

м о ж н о с н я т ь любу ю

с у м м у ,

н е

/ / превышающую

б а л а н с ;

ф у н к ц и я

в о з в р а щ а е т

с н я т у ю с у м м у

p u b l i c d e c i m a l W i t h d r a w ( d e c i m a l m W i t h d r a w a l )

 

{

 

 

 

 

 

 

 

 

/ / Д о п о л н и т е л ь н о е с н я т и е 1 . 5 0

 

 

 

b a s e . W i t h d r a w ( 1 . 5 M ) ;

 

 

 

 

/ / Т е п е р ь с н и м а е м с о с ч е т а к а к о б ы ч н о

 

 

r e t u r n b a s e . W i t h d r a w ( m W i t h d r a w a l ) ;

 

 

p u b l i c

c l a s s

P r o g r a m

 

 

 

 

{

 

 

 

 

 

 

 

 

p u b l i c

s t a t i c v o i d 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 ,

 

 

 

 

 

 

d e c i m a l m A m o u n t )

b a . W i t h d r a w ( m A m o u n t ) ;

 

 

 

 

}

 

 

 

 

 

 

 

 

p u b l i c

s t a t i c v o i d M a i n ( s t r i n g [ ]

a r g s )

 

 

{

 

 

 

 

 

 

 

 

B a n k A c c o u n t

b a ;

 

 

 

 

S a v i n g s A c c o u n t s a ;

 

 

 

 

/ / С о з д а е м б а н к о в с к и й с ч е т , с н и м а е м 1 0 0 , в ы в о д и м

/ / р е з у л ь т а т

 

 

 

 

 

b a = n e w B a n k A c c o u n t ( 2 0 0 М ) ;

 

 

 

b a . W i t h d r a w ( 1 0 0 M ) ;

 

 

 

 

/ / Д е л а е м т о ж е с д е п о з и т н ы м с ч е т о м

 

 

s a

=

ne~w

S a v i n g s A c c o u n t ( 2 0 0 М ,

1 2 ) ;

 

 

s a . W i t h d r a w ( l O O M ) ;

 

 

 

 

(пава 13. Полиморфизм

 

 

 

287


/ / В ы в о д и м с о с т о я н и я с ч е т о в

C o n s o l e . W r i t e L i n e ( " Б а л а н с

B a n k A c c o u n t р а в е н { 0 : С } " ,

b a . B a l a n c e ) ;

C o n s o l e . W r i t e L i n e ( " Б а л а н с

S a v i n g s A c c o u n t р а в е н { 0 : C } " ,

s a . B a l a n c e ) ;

/ / О ж и д а е м п о д т в е р ж д е н и я п о л ь з о в а т е л я

C o n s o l e . W r i t e L i n e ( " Н а ж м и т е < E n t e r > д л я " +

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

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

В этом случае

функция M a i n ()

создает объект

B a n k A c c o u n t с

начальным балан

сом 200 и снимает с него 100. Затем те же действия выполняются с

объектом

Saving'

s A c c o u n t . Когда

функция M a i n ( )

снимает деньги

со счета базового класса,

метод

B a n k A c c o u n t . W i t h d r a w () снимает только указанную сумму (но не более суммы на счету). Когда же функция M a i n () снимает деньги с депозитного счета, метод Saving

s A c c o u n t . W i t h d r a w ( )

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

1.50.

Обратите внимание, что метод S a v i n g s 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 ( ) , а не

работает непосред

ственно с балансом. Если это возможно — пусть базовый класс сам работает» своими членами-данными.

Чем сокрытие лучше проверки флага

На первый взгляд добавление флага в метод 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 не должен беспокоиться о деталях работы S a v i n g s A c c o u n t . Го воря формально, это нарушает принцип инкапсуляции. Базовый класс не должен ничего знать о своих потомках.

Все сказанное приводит ко второй, более сложной проблеме. Предположим, банки по очереди вводит новые с ч е т а — например, C h e c k i n g A c c o u n t , C D A c c o u n t , TBil- l 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 () начинает выглядеть слишком сложным . Каждый новый вид счета приводит, ко все большим изменениям этого метода.

Такое решение совершенно не подходит. Классы должны отвечать сами за себя.

Случайное сокрытие метода базового класса

Метод базового класса может оказаться скрытым случайно. Пусть, например, имеется метод V e h i c l e . T a k e O f f ( ) , который начинает движение транспортного средства. Поз­ же кто-то может расширить класс V e h i c l e , создав класс A i r p l a n e . Понятно, что метод T a k e O f f () этого класса совершенно не тот же, что у класса V e h i c l e . Очевидно, что это случай ложной тождественности — два метода не имеют ничего общего, кроме имени.

К счастью, С# в состоянии обнаружить такую проблему.

288

Часть IV. Объектно-ориентированное программирован®


С# генерирует зловещего вида предупреждение при компиляции рассматривавшейся ране демонстрационной программы H i d i n g W i t h d r a w a l . Из всего длинного текста

предупреждения интерес представляет только небольшая его часть, а именно:

1 .. . S a v i n g s A c c o u n t . W i t h d r a w ( d e c i m a l ) ' h i d e s i n h e r i t e d m e m b e r ' . . . B a n k A c c o u n t . W i t h d r a w ( d e c i m a l ) ' . U s e t h e n e w k e y w o r d i f h i d i n g w a s i n t e n d e d .

C# пытается сообщить, что вы написали метод подкласса, который имеет то же имя, что и метод базового класса. Действительно ли вы хотите именно этого?

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

Неплохо дать указание компилятору С # рассматривать все предупреждения как,

ошибки, по крайней мере на этапе отладки. Дл я этого следует воспользоваться командой мен ю Projects Properties и прокрутить панель Build страницы свойств проекта до раздела Errors and Warnings. Установите значение пара­ метра Warning Level равным 4, наивысшей возможной величине. Кроме того, в подразделе Treat Warnings as Errors выберите флаг АLL. П р и этом при рабо­

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

Описатель n e w , упомянутый в предупреждении и показанный в приведенном далее фрагменте исходного текста, говорит компилятору С# о том, что сокрытие метода пред­ намеренное (тем самым предупреждение устраняется).

//

Теперь

с W i t h d r a w () н и к а к и х п р о б л е м

new

p u b l i c

d e c i m a l W i t h d r a w ( d e c i m a l m W i t h d r a w a l )

{

 

 

// .

. . Никаких иных изменений не требуется . . .

}

Такое использование ключевого слова n e 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 ,

рассматривавшейся

ранее в этой главе. Вызов

B a n k A c ­

count . W i t h d r a w () из

этого

нового метода осуществляется при п о м о щ и

ключевого

слова b a s e .

 

 

 

 

 

Приведенная далее версия функции без ключевого слова b a s e работать не будет:

new p u b l i c

d e c i m a l

W i t h d r a w ( d e c i m a l

m W i t h d r a w a l )

 

{

 

 

 

 

 

d e c i m a l m A m o u n t W i t h d r a w n = W i t h d r a w ( m W i t h d r a w a l ) ;

Глава 13. Полиморфизм

289