Основы наследования (Visual Basic)
Оператор Inherits используется для объявления нового класса, называемого производным классом, который основан на существующем классе, называемом базовым классом. Производные классы наследуют и могут расширять свойства, методы и события, поля и константы, определенные в базовом классе. В следующем разделе описываются некоторые правила наследования, а также модификаторы, используемые для изменения порядка наследования классом или наследования самого класса.
Все классы могут наследоваться по умолчанию, если только они не помечены зарезервированным словом NotInheritable. Классы могут наследовать из других классов проекта или из классов других сборок, на которые ссылается проект.
В отличие от языков, которые позволяют множественное наследование, Visual Basic позволяет только единичное наследование в классах; то есть производные классы могут иметь только один базовый класс. Хотя в классах не поддерживается множественное наследование, они все же могут реализовывать множественные интерфейсы, которые способны эффективно выполнять те же самые задачи.
Чтобы предотвратить предоставление элементов с ограничениями в базовом классе, тип доступа к производному классу должен быть таким же, как и тип доступа к базовому классу, или более строгим. Например, Public класс не может наследовать Friend или Private класс, а Friend класс не может наследовать Private класс.
Модификаторы наследования
Для поддержки наследования Visual Basic вводит следующие инструкции на уровне класса и модификаторы:
Инструкция Inherits определяет базовый класс.
Модификатор NotInheritableне позволяет использовать класс в качестве базового класса.
Модификатор MustInherit определяет, что класс предназначен только для использования в качестве базового класса. Невозможно создать напрямую экземпляры классов MustInherit; их можно создать только как экземпляры базового класса в производном классе. (Другие языки программирования, такие как C++ и C#, используют термин абстрактный класс для описания такого класса.)
Переопределение свойств и методов в производных классах
По умолчанию производный класс наследует свойства и методы от своего базового класса. Если наследуемое свойство или метод в производном классе должен работать другим образом, то оно может быть переопределено. То есть, в производном классе можно определить новую реализацию метода. Следующие модификаторы используются для управления переопределением свойств и методов.
Overridable позволяет переопределение свойства или метода в производном классе.
Overrides переопределяет Overridable свойство или метод, определенное в базовом классе.
NotOverridable не позволяет переопределять свойство или метод в наследующем классе. По умолчанию Public методы являются NotOverridable.
MustOverride требует обязательного переопределения свойства или метода производным классом. При использовании ключевого слова MustOverride определение метода состоит только из инструкций Sub, Function или Property. Другие инструкции не допускаются, и в частности отсутствуют инструкции End Sub и End Function. Методы MustOverride должны объявляться в классах MustInherit.
Допустим, необходимо определить классы для обработки платежных ведомостей. Можно определить универсальный класс Payroll, содержащий метод RunPayroll, который рассчитывает платежную ведомость на неделю. Затем можно использовать Payroll в качестве базового класса для более специализированного класса BonusPayroll, который может использоваться при распределении премий между сотрудниками.
Класс BonusPayroll может наследовать и переопределять метод PayEmployee, определенный в базовом классе Payroll.
В следующем примере определяется базовый класс Payroll, и производный класс BonusPayroll, который переопределяет наследуемый метод PayEmployee. Процедура RunPayroll создает и затем передает объект Payroll и объект BonusPayroll в функцию Pay, которая выполняет метод PayEmployee для обоих объектов.
Const BonusRate As Decimal = 1.45D
Const PayRate As Decimal = 14.75D
Class Payroll
Overridable Function PayEmployee(
ByVal HoursWorked As Decimal,
ByVal PayRate As Decimal) As Decimal
PayEmployee = HoursWorked * PayRate
End Function
End Class
Class BonusPayroll
Inherits Payroll
Overrides Function PayEmployee(
ByVal HoursWorked As Decimal,
ByVal PayRate As Decimal) As Decimal
' The following code calls the original method in the base
' class, and then modifies the returned value.
PayEmployee = MyBase.PayEmployee(HoursWorked, PayRate) * BonusRate
End Function
End Class
Sub RunPayroll()
Dim PayrollItem As Payroll = New Payroll
Dim BonusPayrollItem As New BonusPayroll
Dim HoursWorked As Decimal = 40
MsgBox("Normal pay is: " &
PayrollItem.PayEmployee(HoursWorked, PayRate))
MsgBox("Pay with bonus is: " &
BonusPayrollItem.PayEmployee(HoursWorked, PayRate))
End Sub
Ключевое слово MyBase
Ключевое слово MyBase ведет себя подобно объектной переменной, ссылающейся на базовый класс текущего экземпляра. Ключевое слово MyBase часто используется для обращения к членам базового класса, которые переопределены или скрыты в производном классе. В частности, можно воспользоваться вызовом MyBase.New для явного вызова конструктора базового класса из конструктора производного класса.
Например, при разработке производного класса, переопределяющего метод, унаследованный из базового класса, переопределяемый метод может вызвать метод в базовом классе и изменить возвращаемое значение, как показано в следующем фрагменте кода.
Class DerivedClass
Inherits BaseClass
Public Overrides Function CalculateShipping(
ByVal Dist As Double,
ByVal Rate As Double) As Double
' Call the method in the base class and modify the return value.
Return MyBase.CalculateShipping(Dist, Rate) * 2
End Function
End Class
В следующем списке перечислены ограничения в использовании MyBase.
MyBase относится непосредственно к базовому классу и его унаследованным членам. Его нельзя использовать для доступа к Private членам в классе.
MyBase — это ключевое слово, а не реальный объект. Ключевое слово MyBase не может быть присвоено переменной, передано в процедуры или использовано в сравнении Is.
Метод, квалифицируемый зарезервированным словом MyBase, не требуется определять в соответствующем базовом классе, вместо этого его можно определить в базовом классе, унаследованном косвенным образом. Чтобы ссылка, квалифицируемая зарезервированным словом MyBase, правильно откомпилировалась, один из базовых классов должен содержать метод, сопоставляющий имена и типы параметров, появляющихся в вызове.
Нельзя использовать MyBase для вызова методов MustOverride базового класса.
Нельзя использовать зарезервированное слово MyBase для квалификации самого себя. Таким образом следующий код является недопустимым:
MyBase.MyBase.BtnOK_Click()
Нельзя использовать MyBase в модулях.
Нельзя использовать MyBase для доступа к членам базового класса, помеченным как Friend, если базовый класс находится в другой сборке.
Дополнительные сведения и примеры см. в разделе Практическое руководство. Доступ к переменной, скрытой производным классом (Visual Basic).
Ключевое слово MyClass
Ключевое слово MyClass ведет себя подобно объектной переменной, ссылающейся текущий экземпляр класса, который был изначально реализован. Ключевое слово MyClass напоминает слово Me, однако при каждом вызове метода или свойства MyClass предполагается, что метод или свойство имеет атрибут NotOverridable (Visual Basic). Следовательно, на метод или свойство не оказывает никакого влияния его переопределение в производном классе.
MyClass — это ключевое слово, а не реальный объект. Ключевое слово MyClass не может быть присвоено переменной, передано в процедуры или использовано в сравнении Is.
MyClass ссылается на содержащий класс и его унаследованные члены.
MyClass может использоваться в качестве квалификатора для членов Shared.
Слово MyClass нельзя использовать внутри метода Shared, но можно использовать внутри метода экземпляра для доступа к общему элементу класса.
Нельзя использовать MyClass в стандартных модулях.
MyClass можно использовать для квалификации метода, определенного в базовом классе и не имеющего реализации метода этого класса. Эта ссылка имеет то же самое значение, что и MyBase.Method.
В следующем примере сравниваются Me и MyClass.
Class baseClass
Public Overridable Sub testMethod()
MsgBox("Base class string")
End Sub
Public Sub useMe()
' The following call uses the calling class's method, even if
' that method is an override.
Me.testMethod()
End Sub
Public Sub useMyClass()
' The following call uses this instance's method and not any
' override.
MyClass.testMethod()
End Sub
End Class
Class derivedClass : Inherits baseClass
Public Overrides Sub testMethod()
MsgBox("Derived class string")
End Sub
End Class
Class testClasses
Sub startHere()
Dim testObj As derivedClass = New derivedClass()
' The following call displays "Derived class string".
testObj.useMe()
' The following call displays "Base class string".
testObj.useMyClass()
End Sub
End Class
Несмотря на то, что derivedClass переопределяет testMethod, ключевое слово MyClass в useMyClass сводит к нулю влияние переопределения и компилятор разрешает вызов базового класса версии testMethod.