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

C# для чайников

.pdf
Скачиваний:
183
Добавлен:
27.03.2015
Размер:
15.52 Mб
Скачать

мист просто добавляет в класс H i g h S c h o o l метод N a m e F a v o r i t e ( ) , указывающий имя такого ученика.

И вот — проблема . В университете не н а м е р е н ы определять лучшего студента, но

метод N a m e F a v o r i t e () оказывается

унаследованным . Это м о ж е т показаться не­

большой проблемой — в конце концов,

этот метод в классе U n i v e r s i t y м о ж н о про­

сто игнорировать.

 

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

UML Lite

Унифицированный Язык Моделирования (Unified Modeling Language, U M L ) представляет собой выразительный язык, способный ясно определять взаи­ моотношения объектов в программе. Одно из достоинств U M L заключается в том, что

вы можете не зависеть от конкретного языка программирования .

Ниже перечислены основные свойства U M L .

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

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

Члены со знаком плюс (+) перед именем являются открытыми, со знаком минус (-) — закрытыми . В U M L отсутствует специальный знак для защищенных членов, но некоторые программисты используют для обозначения таких членов символ #.

Закрытые члены доступны только для других членов того же класса; открытые члены доступны всем классам.

Метка { a b s t r a c t } после имени указывает абстрактный класс или метод.

На самом деле U M L использует для этого иное обозначение, но так мне кажется проще. Ведь м ы имеем дело с упрощенной версией — U M L Lite.

Стрелка между двумя классами представляет отношение между ними. Число над лини­ ей означает м о щ н о с т ь — сколько элементов может быть с каждого конца стрелки. Звездочка (*) означает произвольное число. Если число опущено, по умолчанию пред­ полагается значение 1. Таким образом, на рис. 13.1 видно, что один университет может иметь сколько угодно студентов — они связаны отношением один-ко-многим.

Линия с большой открытой или треугольной стрелкой на конце выражает отноше­ ние Я В Л Я Е Т С Я (наследование). Стрелка указывает в иерархии классов на базовый класс. Другие типы взаимоотношений включают отношение С О Д Е Р Ж И Т , которое указывается линией с закрашенным ромбиком со стороны владельца.

' Имеются и другие проблемы . П р и наследовании, показанном на рис. 13.2, как видно из схемы, классы U n i v e r s i t y и H i g h S c h o o l имеют одну и ту же процедуру зачисле­ ния. Как бы странно это ни звучало, будем считать, что это так и есть. Программа разра­ ботана, упакована и отправлена потребителям.

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

299

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

Как избежать указанной проблемы? Понятно, что ее к о р е н ь — в отношениях класса Университет не является школой. Отношение С О Д Е Р Ж И Т также не будет работать — неу­ жели университет содержит школу или ш к о л а — университет? Конечно же, нет. Решение» ключается в том, что и школа, и университет — это специальные типы учебных заведений.

На рис. 13.3 показано более корректное решение . Н о в ы й класс S c h o o l содержит общие свойства двух типов учебных заведений, включая отношения с объектами stu­ d e n t . Более того, класс S c h o o l даже имеет метод E n r o l l ( ) , хотя о н и абстрактны! поскольку и U n i v e r s i t y , и H i g h S c h o o l реализуют его по-разному.

 

Рис.

13.3.

Классы

University и

HighSchool долж­

 

 

ны

иметь общий базовый класс School

 

 

Теперь классы

U n i v e r s i t y и H i g h S c h o o l наследуют общий

базовый

класс. Каж­

дый и з них содержит

свои

уникальные члены:

H i g h S c h o o l —

N a m e F a v o r i t e ! ) ,

a U n i v e r s i t y —

G e t G r a n t

О . Кроме

того, оба

класса перекрывают метод

E n r o l l ( ) ,

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

Введение класса S c h o o l имеет как миниму м два больших преимущества.

1

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

Это изолирует один класс от изменений или дополнений в другой класс. Если

потребуется, например, внести добавления в класс U n i v e r s i t y , то его новые методы никак не повлияют на класс H i g h S c h o o l .

П р о ц е с с в ы д е л е н и я

о б щ и х свойств из схожи х классов н а з ы в а е т с я разложением

классов (factoring).

Это в а ж н о е свойств о о б ъ е к т н о - о р и е н т и р о в а н н ы х языков про-1

г р а м м и р о в а н и я как

по

о п и с а н н ы м в ы ш е п р и ч и н а м , так и с т о ч к и зрения снижения!

и з б ы т о ч н о с т и .

 

 

300

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

Разложение корректно только в том случае, когда отношения наследования со­ ответствуют действительности. М о ж н о выделять общие свойства классов M o u s e и J o y s t i c k , поскольку оба они представляют собой указательные уст­ ройства, но делать то же для классов M o u s e и D i s p l a y будет ошибкой .

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

Puc. 13.4. Разложение классов обычно дает дополнительные уровни в иерар­ хии наследования

Как видите, внесено два

новых класса между U n i v e r s i t y и S c h o o l : H i g h e r -

L e a r n i n g и L o w e r L e v e l .

Например,

новый класс

H i g h e r L e a r n i n g

делится

н а

классы C o l l e g e и U n i v e r s i t y . Такая

многослойная

иерархия — обычное

и даже

же­

лательное явление при разложении, соответствующем реальному миру.

 

 

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

Puc. 13.5. Разложение классов зависит

от решаемой задачи

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

301

Голая концепция, выражаемая абстрактным классом

Вернемся в очередной раз к классу B a n k A c c o u n t .

Большинство методов этого класса не вызывают проблем, поскольку оба типа бан­ ковских счетов одинаково их реализуют. Однако правила снятия со счета оказывают различными, так что вы должны реализовать S a v e i n g s A c c o u n t . W i t h d r a w () не так, как C h e c k i n g A c c o u n t . W i t h d r a w ( ) . Н о как в ы предполагаете реализовать BankAc­ c o u n t . W i t h d r a w ( ) ?

Давайте обратимся за помощью к банковскому служащему. Представляете этот диалог?

— Каковы правила снятия денег со счета? — спрашиваете вы.

С какого счета? Депозитного или чекового?

Со счета, — отвечаете вы. — Просто со счета. Полное непонимание в ответ.

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

вещи, как "просто счет". Все счета (в анализируемом примере) являются либо депозит­ ными, либо чековыми . Концепция счета представляет собой абстракцию, которая объ­ единяет общие свойства конкретных счетов. Она оказывается неполной, поскольку в ней недостает важного свойства W i t h d r a w () (если немного поразмышлять, то найдутся и другие отсутствующие свойства).

Концепция B a n k A c c o u n t является абстракцией.

Как использовать абстрактные классы

Абстрактные классы используются для описания абстрактных концепций. Абстрактный класс — это класс с одним или несколькими абстрактными методами.

Наверное, это не слишком прояснило ситуацию? Тогда вот дополнительное пояснение: абстрактный м е т о д — это метод, описанный при п о м о щ и ключевого слова a b s t r a c t . Ничуть не легче? Тогда следующее добьет вас окончательно: абстрактный метод не име­ ет реализации.

Теперь рассмотрим урезанную демонстрационную программу.

/ / A b s t r a c t l n h e r i t a n c e - к л а с с B a n k A c c o u n t я в л я е т с я

/ / а б с т р а к т н ы м , п о с к о л ь к у в н е м н е с у щ е с т в у е т р е а л и з а ц и и

/ / м е т о д а

W i t h d r a w ( )

n a m e s p a c e

A b s t r a c t l n h e r i t a n c e

{

 

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

/ / A b s t r a c t B a s e C l a s s - с о з д а д и м а б с т р а к т н ы й к л а с с , в

/ / к о т о р о м и м е е т с я т о л ь к о е д и н с т в е н н ы й м е т о д O u t p u t ( ) a b s t r a c t p u b l i c c l a s s A b s t r a c t B a s e C l a s s

{

/ / O u t p u t - а б с т р а к т н ы й м е т о д , к о т о р ы й в ы в о д и т с т р о к у , / / н о т о л ь к о в п о д к л а с с а х , к о т о р ы е п е р е к р ы в а ю т э т о т / / м е т о д

a b s t r a c t p u b l i c v o i d O u t p u t ( s t r i n g s O u t p u t S t r i n g ) ;

}

/ / S u b C l a s s l - п е р в а я к о н к р е т н а я р е а л и з а ц и я к л а с с а

302

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

/ / A b s t r a c t B a s e C l a s s

 

p u b l i c c l a s s S u b C l a s s l

: A b s t r a c t B a s e C l a s s

{

 

o v e r r i d e p u b l i c v o i d

O u t p u t ( s t r i n g s S o u r c e )

{

s t r i n g s = s S o u r c e . T o U p p e r ( ) ;

C o n s o l e . W r i t e L i n e ( " В ы з о в S u b C l a s s l . O u t p u t ( ) и з { о } " ,

s ) ;

}

}

/ / S u b C l a s s 2 - е щ е о д н а к о н к р е т н а я р е а л и з а ц и я к л а с с а / / A b s t r a c t B a s e C l a s s

p u b l i c c l a s s S u b C l a s s 2 : A b s t r a c t B a s e C l a s s

{

o v e r r i d e p u b l i c v o i d O u t p u t ( s t r i n g s S o u r c e )

{

s t r i n g s = s S o u r c e . T o L o w e r ( ) ;

C o n s o l e . W r i t e L i n e ( " В ы з о в S u b C l a s s 2 . O u t p u t ( ) и з { 0 } " , c l a s s P r o g r a m

s ) ;

{

p u b l i c s t a t i c v o i d T e s t ( A b s t r a c t B a s e C l a s s b a )

{

b a . O u t p u t ( " T e s 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 [ ] s t r i n g s )

{

/ / Н е л ь з я с о з д а т ь о б ъ е к т к л а с с а A b s t r a c t B a s e C l a s s , / / п о с к о л ь к у о н — а б с т р а к т н ы й . Е с л и в ы с н и м е т е

/ / к о м м е н т а р и й с о с л е д у ю щ е й с т р о к и , т о С # с г е н е р и р у е т / / с о о б щ е н и е о б о ш и б к е к о м п и л я ц и и

/ / A b s t r a c t B a s e C l a s s b a = n e w A b s t r a c t B a s e C l a s s ( ) ;

/ / Т е п е р ь п о в т о р и м н а ш э к с п е р и м е н т с к л а с с о м S u b c l a s s l C o n s o l e . W r i t e L i n e ( " С о з д а н и е о б ъ е к т а S u b C l a s s l " ) ;

S u b C l a s s l

s c l = n e w S u b C l a s s l ( ) ;

 

T e s t ( s c l )

;

 

 

/ / и к л а с с о м S u b c l a s s 2

 

 

C o n s o l e . W r i t e L i n e ( " \ п С о з д а н и е

о б ъ е к т а S u b C l a s s 2 " ) ;

S u b C l a s s 2 s c 2 = n e w S u b C l a s s 2 ( ) ;

 

T e s t ( s c 2 )

;

 

 

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

 

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 ( ) ;

 

 

В программе сначала определяется класс A b s t r a c t B a s e C l a s s

с единственным аб­

страктным

методом

O u t p u t ( ) . Поскольку

о н объявлен как

a b s t r a c t , метод

Output ()

не имеет реализации, т.е. тела метода.

 

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

303

Класс A b s t r a c t B a s e C l a s s наследуют два подкласса: S u b C l a s s l и SubClass2 Оба — конкретные классы, так как перекрывают метод O u t p u t () "настоящими" мето дами и не содержат собственных абстрактных методов.

Класс может быть объявлен как абстрактный независимо от наличия в нем аб страктных методов. Однако конкретным класс может быть тогда и только то гда, когда все абстрактные методы всех базовых классов выше него сокрыть (перекрыты) реальными методами.

Методы O u t p u t () двух рассматриваемых подклассов немного различны — один из них преобразует передаваемую ему строку в верхний регистр, другой — в нижний. Вы вод программы демонстрирует полиморфную природу класса A b s t r a c t B a s e C l a s s .

С о з д а н и е о б ъ е к т а S u b C l a s s l

В ы з о в S u b C l a s s l . O u t p u t ( )

и з TEST

С о з д а н и е о б ъ е к т а S u b C l a s s 2

В ы з о в S u b C l a s s 2 . O u t p u t ( )

и з t e s t

Н а ж м и т е < E n t e r > д л я з а в е р ш е н и я п р о г р а м м ы . . .

Абстрактный метод автоматически является виртуальным, так что добавлять

ключевое слово v i r t u a l

к ключевому слову a b s t r a c t н е требуется.

Создание абстрактных объектов невозможно

Обратите внимание еще на одну вещь в рассматриваемой демонстрационной про-

грамме: нельзя

создавать объект A b s t r a c t B a s e C l a s s ,

но аргумент функции Test()

объявлен как

объект класса A b s t r a c t B a s e C l a s s

или

одного

из его

подклассов. Это

дополнение

крайне важно. Объекты S u b C l a s s l и

S u b C l a s s 2

могут

быть переданы

в функцию,

поскольку оба являются конкретными подклассами A b s t r a c t B a s e C l a s s ,

Здесь использовано отношение Я В Л Я Е Т С Я . Это очень мощная методика, позволяющая писать высоко обобщенные методы.

Для создания новой иерархии наследования можно также использовать ключевое слово v i r t u a l . Рассмотрим иерархию классов, показанную в приве­ денной далее демонстрационной программе I n h e r i t a n c e T e s t .

/ / I n h e r i t a n c e T e s t

- п р и м е р и с п о л ь з о в а н и я к л ю ч е в о г о с л о в а

/ / v i r t u a l д л я с о з д а н и я н о в о й и е р а р х и и к л а с с о в

n a m e s p a c e I n h e r i t a n c e T e s t

 

{

 

 

u s i n g .

S y s t e m ;

 

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 i n ( s t r i n g [ ]

s t r i n g s )

{

 

 

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 " )

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 ( ) ;

304

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

T e s t l ( b a ) ;

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 " ) ; S a v i n g s A c c o u n t s a = n e w S a v i n g s A c c o u n t ( ) ;

T e s t l ( s a )

;

T e s t 2 ( s a )

;

C o n s o l e . W r i t e L i n e ( " \ п П е р е д а ч а S p e c i a l S a l e A c c o u n t s s a = n e w T e s t l ( s s a ) ;

T e s t 2 ( s s a ) ; T e s t 3 ( s s a ) ;

C o n s o l e . W r i t e L i n e ( " \ п П е р е д а ч а S a l e S p e c i a l C u s t o m e r s s c = n e w T e s t l ( s s c ) ;

T e s t 2 ( s s c ) T e s t 3 ( s s c ) ; T e s t 4 ( s s c ) ;

S p e c i a l S a l e A c c o u n t " ) ; S p e c i a l S a l e A c c o u n t ( ) ;

S a l e S p e c i a l C u s t o m e r " ) ; S a l e S p e c i a l C u s t o m e r ( ) ;

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

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 ( ) ;

p u b l i c

s t a t i c v o i d T e s t l ( B a n k A c c o u n t a c c o u n t )

C o n s o l e . W r i t e L i n e ( " \ t B T e s t ( B a n k A c c o u n t ) " ) ;

a c c o u n t . W i t h d r a w ( 1 0 0 ) ;

p u b l i c

s t a t i c v o i d T e s t 2 ( S a v i n g s A c c o u n t a c c o u n t )

C o n s o l e . W r i t e L i n e ( " \ t B T e s t ( S a v i n g s A c c o u n t ) , " ) ;

a c c o u n t . W i t h d r a w ( 1 0 0 ) ;

p u b l i c

s t a t i c v o i d T e s t 3 ( S p e c i a l S a l e A c c o u n t a c c o u n t )

C o n s o l e . W r i t e L i n e ( " \ t B T e s t ( S p e c i a l S a l e A c c o u n t ) " ) ;

a c c o u n t . W i t h d r a w ( 1 0 0 ) ;

p u b l i c

s t a t i c v o i d T e s t 4 ( S a l e S p e c i a l C u s t o m e r a c c o u n t )

C o n s o l e . W r i t e L i n e ( " \ t B T e s t ( S a l e S p e c i a l C u s t o m e r ) " ) ;

a c c o u n t . W i t h d r a w ( 1 0 0 ) ;

/ / B a n k A c c o u n t - м о д е л и р у е т б а н к о в с к и й с ч е т с н о м е р о м ,

/ / п р и с в а и в а е м ы м п р и с о з д а н и и , и б а л а н с о м

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

taa 13. Полиморфизм

305

/ / W i t h d r a w a l - в ы м о ж е т е с н я т ь с о с ч е т а л ю б у ю с у м м у , н е

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

б а л а н с . В о з в р а щ а е т р е а л ь н о

с н я т у ю с о

/ / с ч е т а с у м м у

 

 

 

 

 

v i r t u a l p u b l i c

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

d W i t h d r a w )

{

 

 

 

 

 

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 . W i t h d r a w ()

11) ;

}

 

 

 

 

 

}

 

 

 

 

 

/ / 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

 

{

 

 

 

 

 

o v e r r i d e p u b l i c v o i d 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 )

{

 

 

 

 

 

C o n s o l e . W r i t e L i n e ( " \ t \ t B b i 3 b i B a e T " +

 

 

 

 

 

 

 

 

" S a v i n g s A c c o u n t . W i t h d r a w ( ) " ) ;

}

 

 

 

 

 

}

/ / S p e c i a l S a l e A c c o u n t - с ч е т и с п о л ь з у е т с я т о л ь к о д л я / / п р о д а ж

p u b l i c c l a s s

S p e c i a l S a l e A c c o u n t : S a v i n g s A c c o u n t

{

 

n e w virtual

p u b l i c v o i d 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 )

{

 

C o n s o l e . W r i t e L i n e ( " \ t \ T B B I 3 B M A E T " +

 

" S p e c i a l S a l e A c c o u n t . W i t h d r a w ( ) " ) ;

}

 

}

/ / S a l e S p e c i a l C u s t o m e r - с ч е т т о л ь к о д л я с п е ц и а л ь н ы х / / п о к у п а т е л е й

p u b l i c c l a s s S a l e S p e c i a l C u s t o m e r : S p e c i a l S a l e A c c o u n t

{

o v e r r i d e p u b l i c v o i d 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 )

{

C o n s o l e . W r i t e L i n e ( " \ t \ T B B I 3 B I B A E T " +

" S a l e S p e c i a l C u s t o m e r . W i t h d r a w ( ) " ) ;

}

}

}

Каждый из указанных классов расширяет наследуемый класс. Заметьте, однако, что метод S p e c i a l S a l e A c c o u n t . W i t h d r a w ( ) помечен как v i r t u a l , что разрывай цепь наследования в этой точке. При рассмотрении с точки зрения B a n k A c c o u n t клас-

сы S p e c i a l S a l e A c c o u n t и

S a l e S p e c i a l C u s t o m e r

выглядят в точности как Sav-

i n g s A c c o u n t . И только при

рассмотрении с точки

зрения S p e c i a l S a l e A c c o u n t

становятся доступны новые версии W i t h d r a w ( ) .

 

Все это показано в приведенной демонстрационной программе . Функция Main() вызывает ряд методов T e s t ( ) , каждый из которых разработан для своего подкласса,]

306

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

Каждая из

версий метода T e s t О вызывает W i t h d r a w () с точки зрения различного

класса объекта.

Вывод программы имеет следующий вид:

Передача

B a n k A c c o u n t

вT e s t ( 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 ( )

1ередача

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

вT e s t ( 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 . W i t h d r a w ( )

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

вы з ы в а е т S a v i n g s A c c o u n t . W i t h d r a w ( )

Передача

S p e c i a l S a l e A c c o u n t

в Test(BankAccount)

вызывает SavingsAccount.Withdraw()

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

вы з ы в а е т S a v i n g s A c c o u n t . W i t h d r a w ( )

вTest(SpecialSaleAccount)

вызывает SpecialSaleAccount.Withdraw()

Передача

S a l e S p e c i a l C u s t o m e r

вT e s t ( 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 . W i t h d r a w ( )

вTest(SavingsAccount)

вызывает SavingsAccount.Withdraw() в Test(SpecialSaleAccount)

вызывает SaleSpecialCustomer.Withdraw()

вT e s t ( S a l e S p e c i a l C u s t o m e r )

в ы з ы в а е т

S a l e S p e c i a l C u s t o m e r . W i t h d r a w ( )

Нажмите < E n t e r >

д л я з а в е р ш е н и я п р о г р а м м ы . . .

Полужирным ш р и ф т о м выделены строки, представляющие особый интерес. Классы

BankAccount и S a v i n g s A c c o u n t работают в точности так, как и

ожидалось. Однако

при вызове

T e s t ( S a v i n g s A c c o u n t ) и S p e c i a l S a l e A c c o u n t ,

и S a l e S p e c i a l ­

Customer

передаются

как

S a v i n g s A c c o u n t . В то

же время

S a l e S p e c i a l C u s ­

tomer при

передаче в

T e s t

( S p e c i a l S a l e A c c o u n t )

работает как наследник этого

пасса, т.е. фактически создается новая иерархия наследования.

Создание новой иерархии

Зачем С# поддерживает создание новой иерархии наследования? Неужели обычного полиморфизма недостаточно?

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

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

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

307

Вы можете решить, что последующие поколения программистов недостойны рая рять написанный вами класс. Заблокировать его от возможных расширений можно nocgj ством ключевого слова s e a l e d — такой класс не сможет выступать в качестве базовой

Рассмотрим следующий фрагмент исходного текста:

u s i n g

S y s t e m ;

p u b l i c

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

{

/ / W i t h d r a w a l - в ы м о ж е т е с н я т ь с о с ч е т а л ю б у ю с у м м у , н е / / п р е в ы ш а ю щ у ю б а л а н с . В о з в р а щ а е т р е а л ь н о с н я т у ю с о / / с ч е т а с у м м у

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

{

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 . W i t h d r a w ( ) " ) ;

}

}

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

{

o v e r r i d e p u b l i c v o i d 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 )

{

 

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 . W i t h d r a w ( )

11) ;

}

}

p u b l i c c l a s s S p e c i a l S a l e A c c o u n t

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

{

 

o v e r r i d e p u b l i c v o i d 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 )

{

C o n s o l e . W r i t e L i n e ( " В ы з о в " +

" S p e c i a l S a l e A c c o u n t . W i t h d r a w () 11) ;

}

}

П р и компиляции данного исходного текста вы получите следующее сообщение ошибке:

' S p e c i a l S a l e A c c o u n t ' : c a n n o t i n h e r i t f r o m s e a l e d c l a s s ' S a v i n g s A c c o u n t '

Ключевое слово s e a l e d дает возможность защитить класс от вмешательства мето дов некоторых подклассов. Например, позволяя программисту расширять класс, реал зующий систему безопасности, вы, по сути, разрешаете создать черный ход, минующий эту систему.

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

308

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]