Наследование

Последнее обновление: 30.10.2015

Одним из ключевых аспектов объектно-ориентированного программирования является наследование (inheritance). Сущность наследования заключается в том, что мы можем расширить функционал уже имеющихся классов с помощью создания наследников этого класса. Допустим, у нас определен следующий класс Person, описывающий отдельного человека:

Public Class Person
    Dim _firstName As String
    Dim _lastName As String

    Public Property FirstName() As String
        Get
            Return _firstName
        End Get
        Set(value As String)
            _firstName = value
        End Set
    End Property

    Public Property LastName() As String
        Get
            Return _lastName
        End Get
        Set(value As String)
            _lastName = value
        End Set
    End Property

    Public Sub Display()
        Console.WriteLine(FirstName & " " & LastName)
    End Sub
End Class

Теперь создадим класс, описывающий сотрудника предприятия - класс Employee. Поскольку этот класс будет реализовывать тот же функционал, что и класс Person, так как сотрудник - это также и человек, то было бы рационально сделать класс Employee производным (или наследником) от класса Person, который, в свою очередь, называется базовым классом или родителем. Чтобы наследовать одни класс от другого, нужно использовать ключевое слово Inherits:

Public Class Employee
    Inherits Person

End Class

По умолчанию все классы могут наследоваться. Однако здесь есть ряд ограничений:

  • Во-первых, не поддерживается двойное наследование, класс может наследоваться только от одного класса. Хотя проблема множественного наследования реализуется с помощью концепции интерфейсов, о которых мы поговорим позже.

  • Во-вторых, при создании производного класса мы должны учитывать тип доступа к базовому классу - тип доступа к производному классу должен быть таким же, как и у базового класса, или более строгим. То есть если базовый класс у нас имеет тип доступа Friend, то производный класс может иметь тип доступа Friend или Private, но не Public.

  • В-третьих, если класс объявлен с модификатором NotInheritable, то от этого класса нельзя наследовать и создавать производные классы. Например, следующий класс не допускает создание наследников:

Public NotInheritable Class Person

End Class

И в этом случае создать от этого класса класс Employee как и любой другой мы не сможем.

Но вернемся к нашему классу Employee. Поскольку он образован от класса Person, то он обладает той же функциональностью, что определена в классе Person. Однако посмотрим, что будет, если мы захотим создать метод для вывода на экран имени сотрудника, которое храниться в переменной _firstName:

Public Class Employee
    Inherits Person
    Public Sub DisplayFirstName()
        Console.WriteLine(_firstName)
    End Sub
End Class

Этот код у нас работать не будет, так как переменная _firstName определена как Private(как вы помните, модификатор Dim аналогичен модификатору Private), поэтому к ней может иметь доступ только класс Person. Но зато в классе Person определено общедоступное свойство FirstName, которое мы можем использовать, поэтому следующий код у нас будет работать нормально:

Public Class Employee
    Inherits Person
    Public Sub DisplayFirstName()
        Console.WriteLine(FirstName)
    End Sub
End Class

Таким образом, производный класс может иметь доступ только к тем членам базового класса, которые определены с модификаторами Public, Friend, Protected и Protected Friend.

Переопределение методов в производных классах

Итак, мы уже можем использовать наши классы в программе:

Sub Main()

    Dim emp As New Employee()
    emp.FirstName = "Bill"
    emp.LastName = "Gates"
    emp.Display()

    Console.ReadLine()
End Sub

Но что если мы захотим добавить в класс Employee свойство, представляющее компанию, в которой сотрудник работает, и выводить в методе Display сведения о компании. То есть мы хотим переопределить функционал метода Display в производном классе. Для этого нам надо в классе Person пометить метод Display модификатором Overridable. А уже в производном классе этот же метод использовать с модификатором Overrides:

'Базовый класс Person
Public Class Person
	'Здесь остальной код
	.....
    Public Overridable Sub Display()
        Console.WriteLine(FirstName & " " & LastName)
    End Sub
End Class

'Производный класс Employee
Public Class Employee
    Inherits Person

    Public Property Company As String

    Public Overrides Sub Display()
        Console.WriteLine(FirstName & " " & LastName & " works in " & Company)
    End Sub
End Class

Чтобы запретить переопределение, вместо Overridable надо использовать ключевое слово NotOverridable (оно используется по умолчанию, если не указано Overridable).

Следует сказать, что мы могли обойтись в нашем примере и без переопределения. Мы могли просто скрыть метод базового класса и объявить в производном классе новый метод с таким же именем. Для этого в объявлении метода в производном классе надо использовать ключевое слово Shadows:

'Базовый класс Person
Public Class Person
	'Здесь остальной код
	.....
    Public Sub Display()
        Console.WriteLine(FirstName & " " & LastName)
    End Sub
End Class

'Производный класс Employee
Public Class Employee
    Inherits Person

    Public Property Company As String

    Public Shadows Sub Display()
        Console.WriteLine(FirstName & " " & LastName & " works in " & Company)
    End Sub
End Class

И если мы вызовем метод Display у объекта класса Employee, то будет использоваться именно метод с модификатором Shadows:

Sub Main()

    Dim emp As New Employee()
    emp.FirstName = "Bill"
    emp.LastName = "Gates"
	emp.Company = "Microsoft"
    emp.Display() 'Здесь будет выведено 'Bill Gates works in Microsoft'

    Console.ReadLine()
End Sub

При этом важно помнить, что Shadows не переопределяет метод базового класса, а лишь скрывает его.

Ключевое слово MyBase.

Теперь добавим в наши классы конструкторы: один конструктор будет без параметров и один с параметрами:

'Базовый класс Person
Public Class Person
	'Здесь остальной код
	.....
	'Конструкторы класса
    Public Sub New()

    End Sub

    Public Sub New(fName As String, lName As String)
        FirstName = fName
        LastName = lName
    End Sub
End Class

'Производный класс Employee
Public Class Employee
    Inherits Person

    'Здесь остальной код
	.....
	'Конструкторы класса
    Public Sub New(fName As String, lName As String, comp As String)
        MyBase.New(fName, lName)
        Company = comp
    End Sub

    Public Sub New()

    End Sub
End Class

В конструктор с параметрами мы передаем значения для свойств класса. В конструкторе класса Person мы устанавливаем имя и фамилию объекта, а в конструкторе класса Employee - имя, фамилию и компанию. Поскольку при создании объекта класса вызываются все конструкторы его родительских классов, то есть при создании объекта класса Employee:

Dim emp As New Employee()

Сначала вызывается конструктор без параметров класса Person, а затем уже конструктор без параметров класса Employee. Поэтому нам нет смысла устанавливать все свойства в конструкторе Employee. И мы передаем часть значений в конструктор родительского класса с помощью ключевого слова MyBase. Это слово используется для получения членов родительского класса. В данном случае мы получили доступ к конструктору.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850