Глава 12
Наследование
Определение одного класса посредством другого, более фундаментального Разница между "является" и "содержит"
Изменение класса объекта
Построение статических членов и членов классов Включение конструкторов в иерархию наследования Вызов конструктора базового класса
бъектно-ориентированное программирование основано на трех принципах: управления доступом (инкапсуляция), наследования других классов и возможно
сти соответствующего отклика (полиморфизм) .
Наследование — распространенная концепция. Я — человек (не считая раннего утра, когда я только-только просыпаюсь) . Я наследую ряд свойств класса H u m a n (человек), такие как зависимость от воздуха, еды, умение разговаривать и т.п. Класс H u m a n насле
дует потребность в воздухе, воде и |
еде от класса Mammal (млекопитающее), а тот, |
всвою очередь, — от класса A n i m a l |
(животное). |
Возможность передачи свойств очень важна. Она позволяет экономно описывать ве щи и концепции. Например, на вопрос ребенка: " Ч т о такое утка?" — ему можно отве тить: "Это птица, которая крякает". Независимо от того, что вы подумали о таком ответе, он содержит значительное количество информации . Ребенок знает, что такое птица, а те перь он знает, что все то же м о ж н о сказать и об утке, а кроме того, у утки имеется до полнительное свойство "кряканье" .
Объектно-ориентированные языки программирования выражают отношение наследо вания, позволяя одному классу наследовать другой, что, в свою очередь, дает возмож ность объектно-ориентированным языкам генерировать модели, более близкие к реаль ности, чем модели, генерируемые языками, объектно-ориентированное программирова ние не поддерживающими.
В приведенной далее |
демонстрационной программе I n h e r i t a n c e E x a m - |
p l e класс S u b c l a s s |
наследован о т класса B a s e C l a s s . |
/ / I n h e r i t a n c e E x a m p l e - п р о с т е й ш а я д е м о н с т р а ц и я н а с л е д о в а н и я using S y s t e m ;
n a m e s p a c e I n h e r i t a n c e E x a m p l e
{
p u b l i c |
|
c l a s s |
B a s e C l a s s |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
p u b l i c |
i n t |
n D a t a M e m b e r ; |
|
|
|
|
|
|
p u b l i c v o i d S o m e M e t h o d O |
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
C o n s o l e . W r i t e L i n e ( " S o m e M e t h o d ( ) " ) ; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
p u b l i c |
c l a s s |
S u b c l a s s |
: |
B a s e C l a s s |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
p u b l i c |
v o i d |
|
S o m e O t h e r M e t h o d ( ) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
C o n s o l e . W r i t e L i n e ( " S o m e O t h e r M e t h o d ( ) " ) ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
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 [ ] |
a r g s ) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
|
/ / С о з д а н и е о б ъ е к т а б а з о в о г о к л а с с а |
|
|
C o n s o l e . W r i t e L i n e ( " Р а б о т а |
с о б ъ е к т о м б а з о в о г о к л а с с а : " • |
B a s e C l a s s b e = n e w B a s e C l a s s О ; |
|
|
b e . n D a t a M e m b e r = 1 ; |
|
|
|
|
|
|
|
b e . S o m e M e t h o d ( ) ; |
|
|
|
|
|
|
|
|
/ / С о з д а н и е о б ъ е к т а п о д к л а с с а |
|
|
|
C o n s o l e . W r i t e L i n e ( " Р а б о т а |
с |
о б ъ е к т о м |
п о д к л а с с а : " ) ; |
|
S u b c l a s s s c = n e w S u b c l a s s О ; |
|
|
|
|
s c . n D a t a M e m b e r = 2 ; |
|
|
|
|
|
|
|
s c . S o m e M e t h o d ( ) ; |
|
|
|
|
|
|
|
|
s c . S o m e O t h e r M e t h o d ( ) ; |
|
|
|
|
|
|
/ / О ж и д а е м п о д т в е р ж д е н и я п о л ь з о в а т е л я |
|
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 ( ) ; |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
Класс |
B a s e C l a s s |
определен |
как |
и м е ю щ и й |
член-данные и простой метод |
S |
M e t h o d ( ) . Функция M a i n () |
создает |
объект be |
базового |
класса B a s e C l a s s и ра |
ет с ним. |
|
|
|
|
|
|
|
|
|
|
|
|
Класс |
S u b c l a s s |
наследуется |
о т |
класса |
B a s e C l a s s |
путем размещения |
и |
класса |
B a s e C l a s s после |
|
двоеточия |
в определении |
класса. S u b c l a s s получает |
ч л е н ы класса B a s e C l a s s |
в |
качестве собственных, а также |
члены, которые могут б |
в него |
добавлены . Ф у н к ц и |
я M a i n () |
демонстрирует, |
что |
S u b c l a s s имеет член-д' |
262 |
Часть IV. Объектно-ориентированное программиров |
nDataMember и член-функцию S o m e M e t h o d ( ) , унаследованные от класса B a s e C l a s s , также новый метод S o m e O t h e r M e t h o d (.), которого нет у базового класса.
Вывод программы на экран выглядит так, как от него и ожидалось (когда все прохо- L дит без сбоев, это всегда приятный сюрприз):
Работа |
с |
о б ъ е к т о м б а з о в о г о к л а с с а : |
SomeMethod () |
работа |
с |
о б ъ е к т о м п о д к л а с с а : |
SomeMethod () |
BomeOtherMethod () |
Нажмите |
|
< E n t e r > д л я з а в е р ш е н и я п р о г р а м м ы . . . |
Это потрясающе
Люди составляют обширные системы, чтобы было проще разбираться в том, что их окружает. Тузик является частным случаем собаки, которая относится к собакообразвым, входящим в состав млекопитающих, и т.д. Так легче познавать мир.
Если привести другой пример, можно сказать, что студент является человеком (точнее, его частным случаем). После этих слов сразу становится известно довольно много о студентах (об американских, естественно). Известно, что они имеют номера социального страхования, слишком много смотрят телевизор и постоянно мечтают о сексе. Но известно все это потому, что эти свойства присущи всем людям .
'В С# говорится, |
что класс S t u d e n t наследует класс P e r s o n . Кроме того, P e r s o n |
является базовым |
классом для |
класса S t u d e n t . Наконец, можно сказать, что |
S t u - |
dent ЯВЛЯЕТСЯ P e r s o n (использование прописных б у к в — общепринятый |
метод |
отражения уникального типа связи). Эта терминология применяется в С + + и других |
объектно-ориентированных языках программирования . |
|
|
|
Заметьте, что хотя S t u d e n t |
и Я В Л Я Е Т С Я P e r s o n , обратное |
не верно. P e r s o n |
не |
ЯВЛЯЕТСЯ S t u d e n t (такое |
выражение следует трактовать |
в о б щ е м смысле, |
по |
скольку конкретный человек, конечно же, может оказаться студентом). Существует много людей, являющихся членами класса P e r s o n , но не членами класса S t u d e n t . Кроме того, класс S t u d e n t имеет средний балл, a P e r s o n — нет.
Свойство наследования транзитивно. Например, если определить новый класс G r a d u a t e - Student как подкласс класса S t u d e n t , то он тоже будет наследником P e r s o n . Это зна чит, что будет выполняться следующее: если G r a d u a t e S t u d e n t ЯВЛЯЕТСЯ S t u d e n t и Student ЯВЛЯЕТСЯ P e r s o n , т о G r a d u a t e S t u d e n t ЯВЛЯЕТСЯ P e r s o n .
Зачем нужно наследование
Наследование выполняет ряд важных функций. Вы можете решить, что главная из них — уменьшить количество ударов по клавишам в процессе ввода программы. И это тоже — вам не надо заново вводить все свойства P e r s o n при описании класса S t u d e n t .
Однако более важна возможность повторного использования (reuse). Нет нужды на чинать каждый новый проект с нуля, если м о ж н о воспользоваться готовыми программ ными компонентами.
С р а в н им разработку программного обеспечения с другими областями человеческой деятельности. Многие ли производители автомобилей начинают проектировать новую модель с разработки для этого новых шурупов, болтов и гаек? И даже если это так, что вы скажете о разработке новых молотков, отверток и прочего инструментария? Ко нечно же н е т — по возможности при проектировании и сборке новой модели мага мально используются детали и части старой — не только болты и гайки, но и крупна узлы, такие как компрессоры или даже двигатели.
Наследование позволяет настроить уже имеющиеся программные компоненты. Ста р ы е классы могут быть адаптированы для применения в новых программах без внесения в них кардинальных изменений. Существующий класс наследуется — с расширением его в о з м о ж н о с т е й — н о в ы м подклассом, который содержит все необходимые добавления и изменения. Если базовый класс написан кем-то иным, у вас может просто не быть во можности вносить в него изменения, и наследование оказывается единственным спосо бом его использования.
Данная возможность тесно связана с третьим преимуществом применения наследова ния. Представим ситуацию, когда вы наследуете базовый класс. Позже выясняется, что в нем имеется ошибка, которую нужно исправить. Если вы модифицировали класс для его повторного использования, вы должны вручную внести изменения и протестировав каждое приложение в отдельности. П р и наследовании класса без внесения изменений в общем случае исправляете только базовый класс, не затрагивая сами приложения.
Однако главное преимущество наследования в том, что оно описывает реальный мир таким, каков он есть.
Банк поддерживает несколько типов счетов. Один из них — депозитный счет — обладает всеми свойствами простого банковского счета плюс воз можность накопления процентов. Такое отношение на языке С# моделируется в приведенной далее демонстрационной программе. Версия этой про граммы на компакт-диске включает некоторые изменения из следующего раздела, так что она несколько отличается от приведенного здесь листинга.
/ / S i m p l e 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 ; з д е с ь н е / / в и р т у а л ь н ы е м е т о д ы ( о н и х б у д е т с к а з а н о u s i n g S y s t e m ;
S a v i n g s A c c o u n t и с п о л ь з у ю т с я в г л а в е 1 3 )
n a m e s p a c e S i m p l e 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 c l a s s B a n k A c c o u n t / / t h e b a s e c l a s s
{
/ / Н о м е р а с ч е т о в н а ч и н а ю т с я с 1 0 0 0 и о б р а з у ю т |
/ / |
в о з р а с т а ю щ у ю п о с л е д о в а т е л ь н о с т ь |
p u b l i c s t a t i c i n t n N e x t A c c o u n t N u m b e r = 1 0 0 0 ; |
/ / |
Н о м е р с ч е т а и б а л а н с д л я к а ж д о г о о б ъ е к т а с в о и |
|
|
|
p u b l i c |
i n t n A c c o u n t N u m b e r ; |
p u b l i c |
d e c i m a l m B a l a n c e ; |
/ / |
I n i t - И н и ц и а л и з а ц и я с ч е т а о ч е р е д н ы м с в о б о д н ы м |
/ / |
н о м е р о м и к о н к р е т н ы м н а ч а л ь н ы м б а л а н с о м ( п о у м о л ч а н и ю |
264 |
Часть IV. Объектно-ориентированное программирован |
// н о л ь )
p u b l i c v o i d I n i t B a n k A c c o u n t ( )
{
I n i t B a n k A c c o u n t ( 0 ) ;
}
p u b l i c v o i d I n i t 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 )
{
n A c c o u n t N u m b e r = + + n N e x t A c c o u n t N u m b e r ; m B a l a n c e = m l n i t i a l B a l a n c e ;
}
/ / С в о й с т в о 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 get { return mBalance;}
}
/ / D e p o s i t - П о з в о л е н л ю б о й p u b l i c v o i d D e p o s i t ( d e c i m a l
{
п о л о ж и т е л ь н ы й в к л а д m A m o u n t )
if (mAmount > 0)
{
m B a l a n c e + = m A m o u n t ;
/ / |
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 ) |
i f ( B a l a n c e < = m W i t h d r a w a l ) |
/ / и с п о л ь з у е т с я с в о й с т в о |
{ |
/ / B a l a n c e |
m W i t h d r a w a l = B a l a n c e ; |
|
} |
|
m B a l a n c e - = m W i t h d r a w a l ; |
|
r e t u r n m W i t h d r a w a l ; |
|
}
/ / T o S t r i n g - p u b l i c s t r i n g
с т р о к а с и н ф о р м а ц и е й о с о с т о я н и и с ч е т а T o B a n k A c c o u n t S t r i n g ( )
r e t u r n S t r i n g . F o r m a t ( " { 0 } |
- { l : C } " , |
n A c c o u n t N u m b e r , B a l a n c e ) ; |
// S a v i n g s A c c o u n t - б а н к о в с к и й с ч е т с н а к о п л е н и е м |
// п р о ц е н т о в |
|
public 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 ; |
/ / I n i t S a v i n g s A c c o u n t - |
и с п о л ь з у е т п р о ц е н т н у ю с т а в к у , |
/ / в ы р а ж а е м у ю ч и с л о м о т |
0 д о 1 0 0 |
p u b l i c v o i d |
I n i t S a v i n g s A c c o u n t ( d e c i m a l |
m l n t e r e s t R a t e ) |
{ |
|
|
I n i t S a v i n g s A c c o u n t ( 0 , m l n t e r e s t R a t e ) ; |
|
} |
|
|
p u b l i c v o i d |
I n i t 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 , |
|
d e c i m a l m l n t e r e s t R a t e ) |