Дата публикации статьи: 14.11.2004 14:41

Гайдар Магдануров
Основы объектно-ориентированного программирования
Часть вторая. Перегрузка

  • Вступление
  • Перегрузка функций
  • Перегрузка конструкторов
  • Перегрузка операторов
  • Заключение
  •   Обсудить в форуме
  • Вступление

        В этой статье посвященного объектно-ориентированному программированию (ООП) циклу, будет подробно рассмотрена перегрузка (overloading) функций, конструкторов и операторов. Надеюсь, что Вы уже привыкли к термину перегрузка, поскольку теперь я буду называть эту процедуру так, как принято в русскоязычной литературе.  Сразу же оговорюсь, что все приведенные сведения относительно перегрузки операторов относятся только к версии Visual Basic 2005, поскольку в предыдущих версиях перегрузка операторов не поддерживалась.

    Перегрузка функций

        В предыдущей статье, давшей основные представления о ООП, я уже говорил о том, что такое перегрузка, но, как говорят, "повторенье - мать ученья", поэтому не лишним будет еще раз сформулировать определение. Перегрузка - это возможность написать несколько функций или свойств с одним и тем же именем. Во избежание возможных конфликтов имен перегружаемые функции и свойства должны отличатся типом или количеством параметров.
        Рассмотрим подробнее, зачем и как используется перегрузка. Создадим некоторый базовый класс от которого унаследуем несколько дочерних классов в которых переопределим функции базового класса. Пусть этот класс называется Man и представляет собой "человека" у которого есть "свойства" - страна проживания, имя и "методы" - сказать нечто и поприветствовать.

    Public Class Man
        Public mName As String
        Public mCountry As String
    
        Public Sub Say(ByVal Words As String)
            MsgBox(Words, MsgBoxStyle.Exclamation, Me.mName)
        End Sub
    
        Public Sub SayHello()
            Me.Say("Hello!")
        End Sub
    
        Public Property Country()
            Get
                Return Me.mCountry
            End Get
            Set(ByVal value)
                Me.mCountry = value
            End Set
        End Property
    End Class
    

    Здесь используется конструктор, позволяющий задать имя человека. Типичное "поведение" данного класса:

    Dim mMan As New Man
    mMan.SayHello()

    Теперь унаследуем от этого класса два других класса в которых переопределим методы и свойства:

    Public Class Russian
        Inherits Man
        Public Overloads Function SayHello()
            Me.Say("Привет!")
        End Function
    End Class
    
    
    Public Class American
        Inherits Man
        Public Overloads Function SayHello()
            Me.Say("Hi!")
        End Function
        Public Overloads Property Country()
            Get
                Return mCountry
            End Get
            Set(ByVal value)
                Me.mCountry = "The " & value
            End Set
        End Property
    
    End Class
    

        Какую выгоду получаем мы в этом случае? Прежде всего, при наследовании класса мы избавляемся от необходимости писать похожий код еще раз, а благодаря перегрузке мы можем видоизменить класс так, как нам это нужно для получения требуемого результата. Но это простейший пример, усложним его на примере перегрузки конструкторов.

    Перегрузка конструкторов

        Прежде всего обсудим конструкторы. Как уже было сказано в предыдущей статье, конструктор - метод, сопровождающий "рождение" объекта. Возможно, что Вам не очевидно, зачем может быть необходима перегрузка конструктора, но сейчас я проясню эту ситуацию. Допустим, что класс может быть инициализирован переменными различных типов, при этом необходимо обеспечить простоту работы с классом, то есть, вне зависимости от типа, формата или значения переданного параметра класс должен быть "рожден" в соответствии со своей внутренней структурой.
        Кстати, а Вы задумывались, бывают ли классы без конструкторов? Думаете, если Вы создаете класс и не создаете конструктор, то класс не имеет своего конструктора? А вот и нет! Автоматически компилятор создает конструктор по умолчанию, без параметров, но прекрасно выполняющий свою задачу - инициализирующий экземпляр класса. Так что, классов без конструкторов не бывает.
        Так, лирическое отступление закончилось, теперь перейдем непосредственно к примеру. Пусть есть класс представляющий собою целые числа. Да-да, такой класс уже есть и называется Integer, но мы создадим свой класс MyInteger, на примере которого продемонстрируем возможности перегрузки конструкторов.

      Public Class MyInteger
    
        Private mValue As Integer
    
        Public Sub New()
            mValue = 0
        End Sub
    
        Public Sub New(ByVal Value As Integer)
            mValue = Value
        End Sub
    
        Public Sub New(ByVal Value As Double)
            mValue = CType(Value, Integer)
        End Sub
    
        Public Sub New(ByVal Value As String)
            mValue = CType(Value, Integer)
        End Sub
    
        Public Overloads Function ToString()
            Return mValue.ToString
        End Function
    
    End Class

        Таким образом, значение mValue может быть инициализировано не только значением типа Integer, но и String и Double, что позволяет создавать экземпляры этого класса не заботясь о типах передаваемых значений. Например так:

        Dim mDouble As New Double
        mDouble = 1.2994593456
        Dim mInt As New MyInteger(mDouble)
        MsgBox(mInt.ToString)
    

    Или так:

        Dim mInt As New MyInteger("3")
        MsgBox(mInt.ToString)

    Вы еще не убедились, что перегрузка весьма "занятная штука"? Что ж, "Вы песен хотите? Их есть у меня...". В следующей части статьи мы расширим класс myInteger еще немного.

    Перегрузка операторов

        Допустим, мы хотим суммируя два объекта типа MyInteger получить сумму значений и сохранить в третьем объекте того же типа. Но как это сделать, попробовав так:

    Dim mInt1 As New MyInteger(2)
    Dim mInt2 As New MyInteger(3)
    Dim mInt3 As New MyInteger
    mInt3 = mInt2 + mInt1

        Вы убедитесь, что компилятор еще не умеет читать Ваши мысли и исполнять желания, поэтому необходимо ему объяснить, что же Вы от него хотите. К сожалению, до выхода Visual Basic 2005 переопределить операторы не представлялось возможным, поэтому приходилось искать обходные пути, например такие:

    Public Function Add(ByVal mInt1 As MyInteger, ByVal mInt2 As MyInteger)
        Me.mValue = mInt1.mValue + mInt2.mValue
    End Function

    Включив подобную функцию в класс мы могли в дальнейшем использовать такой метод сложения значений, содержащихся в объектах типа MyInteger:

    Dim mInt1 As New MyInteger(2)
    Dim mInt2 As New MyInteger(3)
    Dim mInt3 As New MyInteger
    mInt3.Add(mInt2, mInt1)
    MsgBox(mInt3.ToString)

        Это не так логично и очевидно, приятно и красиво (и т.д. и т.п.), как использование столь родного знака "+". Что ж, с появлением Visual Basic 2005 мы можем переопределить оператор "+", так, чтобы он выполнял требующиеся действия.

    Public Overloads Shared Operator +(ByVal mInt1 As MyInteger, ByVal mInt2 As MyInteger)
       Dim resInt As New MyInteger()
       resInt.mValue = mInt1.mValue + mInt2.mValue
       Return resInt
    End Operator

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

    Заключение

        В этой небольшой и весьма простой статье было рассказано о перегрузке операторов, функций и свойств. Приведенных сведений достаточно для дальнейшего самостоятельного изучения материала, которое, я надеюсь, последует сразу же за прочтением данной статьи. Кодируйте, компилируйте и запускайте! Если что-то не получится, пишите мне.