Знакомство с наследованием
Начнем с повторения некоторых терминов. Класс, взятый за основу при определении нового класса, называется базовым классом. Класс, определяемый на основе базового класса, называется производным классом. Производный класс автоматически наследует всю открытую функциональность базового класса, однако эта функциональность может переопределяться в производном классе и дополняться новыми возможностями.
Следующий пример наглядно показывает, как это происходит. Допустим, у нас имеется компания с передовой политикой в области материального стимулирования. Каждый раз, когда заработная плата всех служащих компании повышается на 5%, для программистов прибавка составляет 6%. Вам поручено разработать систему учета кадров для этой компании. Вы решаете определить класс Programmer, производный от Employee, и переопределить метод RaiseSal агу в классе Programmer, чтобы отразить автоматическую (и вполне заслуженную!) надбавку.
Итак, приступим к программированию цепочки наследования Employee—>Programmer. Допустим, у нас уже имеется класс Publiс Employee, который входит в решение или включается в него командой Project > References. В этом случае начало кода класса Programmer будет выглядеть так (ключевая строка выделена жирным шрифтом):
Public Class Programmer
Inherits Employee
End Class
Ключевое слово Inherits должно находиться в первой не пустой и не содержащей комментария строке после имени производного класса (кстати, IntelliSense подскажет имена возможных базовых классов). Учтите, что производный класс не может объявляться с модификатором Publ i с, если базовый класс объявлялся с модификатором Friend или Private. Это связано с тем, что модификатор уровня доступа в производном классе не может быть менее ограничивающим, чем модификатор базового класса. С другой стороны, он может устанавливать более жесткие ограничения, поэтому от базового класса с уровнем доступа Publ i с можно объявить производный класс с уровнем Friend.
Следующим шагом в построении производного класса должно стать правильное определение конструктора.
Поскольку производный класс должен обладать как минимум теми же возможностями, что и базовый, конструкторы производных классов часто вызывают конструкторы базовых классов для правильной инициализации полей базового класса и передают им аргументы, которые должны использоваться при инициализации. При этом используется специальное ключевое слово MyBase:
Public Sub New(ByVal theName As String, ByVal curSalary As Decimal)
MyBase.NewCName.curSalary)
End Sub
Ключевая строка, выделенная жирным шрифтом, вызывает конструктор базового класса Empl oyee и инициализирует его поля. Если вы забудете вызвать MyBase. New в том случае, когда конструктор базового класса вызывается с аргументами, VB .NET выдает сообщение об ошибке следующего вида:
C:\vb net book \chapter 5 \Examplel \Examplel \Modulel.vb(55):
'Examplel.Programmer'.the base class of 'Examplel.Employee'.
does not have an accessible constructor that can be called with
no arguments. Therefore.the first statement of this constructor
must be a call to a constructor of the base class via 'MyBase.New'
or another constructor of this class via 'MyClass.New' or 'Me.New'.
Хорошо бы, чтобы все сообщения об ошибках были настолько содержательными и понятными. Компилятор напоминает о том, что при отсутствии у базового класса безаргументного конструктора производный класс должен содержать хотя бы один вызов MyBase. New. После включения в программу вызова MyBase. New возникает очень интересный вопрос: как обращаться к полям базового класса? Следующее правило на первый взгляд может вас удивить:
Производный класс не обладает привилегированным доступом к полям базовою класса.
Из этого правила следует, что производный класс Programmer не получает доступа к закрытым полям базового класса Employee. Предположим, заработная плата хранится в закрытом поле базового класса с именем m_Sal ary и вы пытаетесь включить в код метода RaiseSalary класса Programmer следующий фрагмент:
Public Sub New(ByVal theName As String. ByVal curSalary As Decimal)
MyBase.New(theName. curSalary)
MyBase.m_salary = 1.2 * curSalary End Sub
Компилятор выдает сообщение об ошибке:
'Examplel.Employee.m_Salary'is Private.and is not accessible
in this context.
В повседневной жизни существует хорошая аналогия — родители устанавливают правила поведения для детей, а не наоборот.
Что же делать? Если вы хотите, чтобы производный класс получил доступ к некоторым возможностям базового класса, об этом должен позаботиться сам базовый класс. В следующем разделе будет показано, как это делается.