Абстрактные базовые классы. Пример: класс CollectionBase.
На стадии проектирования наследственных связей в программе часто выясняется, что многие классы обладают целым рядом сходных черт. Например, внештатные сотрудники не относятся к постоянным работникам, но и те и другие обладают рядом общих атрибутов – именем, адресом, кодом налогоплательщика и т. д. Было бы логично выделить все общие атрибуты в базовый класс PayableEntity. Этот прием, называемый факторингом, часто используется при проектировании классов и позволяет довести абстракцию до ее логического завершения.
В классах, полученных в результате факторинга, некоторые методы и свойства невозможно реализовать, поскольку они являются общими для всех классов в иерархии наследования. Например, класс PayableEntity, от которого создаются производные классы штатных и внештатных работников, может содержать свойство с именем TaxID. Обычно в процедуре этого свойства следовало бы организовать проверку кода налогоплательщика, но для некоторых категорий внештатных работников эти коды имеют особый формат. Следовательно, проверка этого свойства должна быть реализована не в базовом классе PayableEntity, а в производных классах, поскольку лишь они знают, как должен выглядеть правильный код.
В таких ситуациях обычно определяется абстрактный базовый класс. Абстрактным называется класс, содержащий хотя бы одну функцию с ключевым словом MustOverride; при этом сам класс помечается ключевым словом Mustlnherit. Ниже показано, как может выглядеть абстрактный класс PayableEntity:
Public Mustlnherit Class PayableEntity Private m_Name As String Public Sub New(ByVal itsName As String) m_Name = itsName End Sub Readonly Property TheName()As String Get Return m_Name End Get End Property Public MustOverride Property TaxID()As String End Class
Обратите внимание: свойство TaxID, помеченное ключевым словом MustOverride, только объявляется без фактической реализации. Члены классов, помеченные ключевым словом MustOverride, состоят из одних заголовков и не содержат команд End Property, End Sub и End Function. Доступное только для чтения свойство TheName при этом реализовано; из этого следует, что абстрактные классы могут содержать как абстрактные, так и реализованные члены. Ниже приведен пример класса Егорlоуее, производного от абстрактного класса PayableEntity:
Public Class Employee Inherits PayableEntity Private m_Salary As Decimal Private m_TaxID As String Private Const LIMIT As Decimal = 0.1D Public Sub NewCByVal theName As String, ByVal curSalary As Decimal. ByVal TaxID As String) MyBase.New(theName) m_Salary = curSalary m_TaxID = TaxID End Sub Public Overrides Property TaxID() As String Get Return m_TaxID End Get Set(ByVal Value As String) If Value.Length <> 11 then ' См. главу 7 Else m_TaxID = Value End If End Set End Property Readonly Property Salary() As Decimal Get Return MyClass.m_Salary End Get End Property Public Overridable Overloads Sub RaiseSalary(ByVal Percent As Decimal) If Percent > LIMIT Then ' Операция запрещена – необходим пароль Console.WriteLineC'NEED PASSWORD TO RAISE SALARY MORE " & _ "THAN LIMIT!!!!") Else m_Salary =(1D + Percent) * m_Salary End If End Sub Public Overridable Overloads Sub RaiseSalary(ByVal Percent As Decimal. ByVal Password As String) If Password ="special" Then m_Salary MID + Percent) * m_Salary End If End Sub End Class