ПОНЯТНО О Visual Basic NET (том 3)

       

Абстрактные классы


Владельцы участков в нашем товариществе стали огораживать их всяк на свой манер: у одних участки прямоугольные, у других треугольные, у третьих круглые. Для нашего проекта это значит, что периметры теперь нужно считать по разным формулам. Соответственно создаем три класса: Участок_прямоугольный, Участок_треугольный и Участок_круглый. Их коды во многом одинаковы и различаются только исходными данными и функцией Периметр. Следовательно, целесообразно организовать наследование. Но кто кого будет наследовать? Вроде, все три класса равноправны. Из соображений стройности и логичности системы классов нам не хочется один из них делать родителем. Что же делать? Поступают так. Создают один класс, родительский для всех трех, и включают в него код, общий для всех трех классов. Поскольку функция Периметр разная для всех классов, то в этот класс включают только ее заголовок, без тела. Ясно, что от такого бестелесного класса нельзя создавать объекты, поэтому его называют абстрактным классом и помечают словом MustInherit. Вот этот класс:

Public MustInherit Class Участок_абстрактный

    Public Владелец As String

    Public Высота_забора As Integer

    Public Shared Расход_краски_на_кв_м As Integer

    Public MustOverride

Function Периметр() As Integer

    Public Overridable Function Площадь_забора() As Integer

        Return Периметр() * Высота_забора

    End Function

    Public Function Расход_краски_на_забор() As Integer

        Return Расход_краски_на_кв_м * Площадь_забора()

    End Function



End Class

Вы видите, что функция в этом классе помечена словом MustOverride, что означает «Необходимо пересилить, переопределить». От функции присутствует только заголовок. Ситуация того же смысла, что и со словом Overridable, только более строгая. Это значит, что обращаться к функции в этом классе бесполезно, все равно у нее нет тела, а вот в коде наследников эту функцию написать можно и нужно, причем тело функции у каждого наследника может быть своим. К этим функциям и будем обращаться. Вот три наших класса:


Public Class Участок_прямоугольный

    Inherits Участок_абстрактный

    Public Длина, Ширина As Integer

    Public Overrides

Function Периметр() As Integer

        Return    2 * (Длина + Ширина)

    End Function

End Class

Public Class Участок_треугольный

    Inherits Участок_абстрактный

    Public Сторона1, Сторона2, Сторона3

As Integer

    Public Overrides

Function Периметр() As Integer

        Return    Сторона1 + Сторона2 + Сторона3

    End Function

End Class

Public Class Участок_круглый

    Inherits Участок_абстрактный

    Public Радиус As Integer

    Public Overrides

Function Периметр() As Integer

        Return    2 * Math.PI * Радиус

    End Function

End Class

Вы видите, что абстрактные классы помогают поддерживать в проекте стройную иерархию классов.

В нашу систему классов я могу включить и класс Участок_штакетник. Я сделаю его сыном прямоугольного участка и, значит, внуком абстрактного:

Public Class Участок_штакетник

    Inherits Участок_прямоугольный

    Public Overrides Function Площадь_забора() As Integer

        Return 0.5 * MyBase.Площадь_забора

    End Function

End Class

Вы видите, что он может посчитать площадь штакетника только вокруг прямоугольного участка. Вопрос о штакетнике вокруг треугольного и круглого участков оставляю открытым для вашего размышления.


Содержание раздела