Основы наследования
В предыдущей главе кратко упоминались два столпа объектно-ориентированного программирования в VB.NET: наследование реализации, обеспечивающее возможность многократного использования кода, и наследование интерфейсов, то есть "контракт", которому должны соответствовать некоторые аспекты поведения класса. Обе разновидности наследования будут подробно рассмотрены в этой главе.
Для начала мы покажем, как в VB.NET организовано наследование реализации. К сожалению, при изучении этой темы никак нельзя ограничиться поверхностным знакомством. Дело в том, что непродуманные действия программиста при наследовании реализации приводят к весьма неприятным последствиям, поэтому в этой главе мы потратим довольно много времени, показывая, как избежать этих опасностей за счет тщательного проектирования иерархии наследования.
После описания механики и основных принципов наследования реализации мы во всех подробностях изучим класс Object, являющийся предком всех объектов .NET. Завершая описание наследования реализации, мы покажем, как в .NET решается проблема неустойчивости базовых классов, вызывающая немало хлопот при наследовании реализации в других объектно-ориентированных языках – таких, как Java и С++. Не пугайтесь термина "проблема неустойчивости базовых классов"; речь идет всего лишь о том, что непродуманные изменения базового класса могут нарушить работу производных классов.
Примечание
С этого момента под термином "наследование" будет пониматься наследование реализации. Если речь пойдет о программном коде, использующем наследование интерфейсов, мы будем употреблять термин "реализация интерфейсов". На первый взгляд терминология кажется крайне запутанной, но большинство программистов быстро привыкают к этим сокращенным обозначениям.
От наследования мы перейдем к реализации интерфейсов в VB.NET. В завершение этой главы вы узнаете, как использовать важнейшие интерфейсы .NET Framework IComparable, ICloneable и IDisposable.
Примечание
Программисты с опытом использования интерфейсов BVB5 и VB6 будут приятно удивлены тем, насколько понятнее выглядят программы при реализации интерфейсов в VB.NET. В синтаксисе произошли заметные изменения к лучшему.
Хотя наследование не является панацеей ООП и во многих ситуациях лучше воспользоваться интерфейсами, не стоит полагать, что без наследования можно как-нибудь обойтись. Наследование – замечательное средство, способное сэкономить немало времени и сил… если им правильно пользоваться. Критерий правильного использования прост: не используйте наследование, если у вас нет абсолютной уверенности в существовании логической связи типа "является частным случаем".
Класс А объявляется производным от класса В только в том случае, если вы точно знаете, что сейчас и в сколь угодно отдаленном будущем объект А может использоваться вместо объекта В и это не вызовет никаких проблем.
(Помните пример из главы 4? Оформляя внештатного работника по правилам для обычных сотрудников, вы наживете неприятности с налоговой инспекцией. Класс Contractor не должен объявляться производным от класса Employee даже при том, что "они обладают рядом сходных черт.)
Ниже этот фундаментальный принцип приведен в слегка измененном, более абстрактном виде, ориентированном на практическое программирование.