Home

Operator Overloading

   

Fundamentals of Overloading an Operator

 

Introduction

 

In elementary school, we learned how to perform arithmetic operations such as adding 2 to 5 to get 7. We also learned somehow how to add letters to create a word, how to add words to create a sentence, and how to add symbols to create abbreviations. In programming, we learn how to create classes that are made of more than one value. When necessary, we may want to add the values of those classes to get new values. Unfortunately, those classes are not equipped to perform arithmetic operations or comparisons on their objects. Fortunately, if you judge it necessary, you can write code that makes it possible.

We know many of the operators available in the Visual Basic language. We also reviewed some of the ways they can be used. We saw that there are rules that must be followed when using any of those operators.

Operator overloading consists of customizing the behavior of a Visual Basic operator to be able to apply it on the values of a class. This means that you must create a special behavior in your class for a particular operator you want to use.

A class whose operators you want to overload primarily starts like any class. You can add any members you judge necessary to it. Make sure you provide appropriate and realistic constructors so the class can be initialized appropriately. The other important detail you should take care of is how the value of the class will be accessed outside. Probably the easiest way to do this consists of overriding the ToString() method in it.

Here is an example of a class:

Public Class Natural
    Public Number As Integer

    Public Sub New(ByVal N As Integer)
        Number = N
    End Sub

    Public Overrides Function ToString() As String
        Return Number.ToString()
    End Function
End Class

ApplicationApplication: Introducing Operator Overloading

  1. Start Microsoft Visual Basic
  2. To start a new application, on the Start Page, click File -> New Project...
  3. In the middle list, click Class Library
  4. Change the Name to Mathematics
  5. Click OK
  6. In the Solution Explorer, right-click Class1.vb and click Rename
  7. Type Arithmetic.vb and press Enter
  8. To save the project, on the Standard toolbar, click the Save All button Save All
  9. Make a note of the location and click Save
  10. Change the file as follows:
    Public Class Arithmetic
        Public Shared Function GreatestCommonDivisor(ByVal a As Long, ByVal b As Long)
            Dim Remainder As Long
    
            While b <> 0
                Remainder = a Mod b
                a = b
                b = Remainder
            End While
    
            Return a
        End Function
    End Class
  11. To create the library, in the Solution Explorer, right-click Mathematics and click Build
  12. To create a new project, on the main menu, click File -> New Project...
  13. In the middle list, click Console Application
  14. Change the name to Algebra1
  15. Click OK
  16. On the main menu, click Project -> Algebra1 Properties
  17. Click the arrow of the Application Type box and select Windows Forms Application
  18. In the Solution Explorer, right-click Module1.vb and click Rename
  19. Type Algebra.vb and press Enter twice
  20. Change the document as follows:
    Module Algebra
    
        Public Function Main() As Integer
    
            Return 0
        End Function
    
    End Module
  21. In the Solution Explorer, right-click Algebra1 and click Add Reference...
  22. Click the Browse tab
  23. Locate the folder where the Mathematics library was created
  24. Select Mathematics.dll
  25. Click OK
  26. To create a new class, in the Class View, right-click Algebra1 -> Add -> Class...
  27. Set the Name to Rational
  28. Click Add
  29. Change the file as follows:
    Imports Mathematics
    
    Public Class Rational
        Private Num As Long
        Private Den As Long
    
        Public Sub New(ByVal n As Long, ByVal d As Long)
            Num = n
            Den = d
        End Sub
    
        Public Property Numerator() As String
            Get
                Return Num / Arithmetic.GreatestCommonDivisor(Num, Den)
            End Get
            Set(ByVal value As String)
                Num = value
            End Set
        End Property
    
        Public Property Denominator() As String
            Get
                Return Den / Arithmetic.GreatestCommonDivisor(Num, Den)
            End Get
            Set(ByVal value As String)
                Den = value
            End Set
        End Property
    
        Public Overrides Function ToString() As String
            Dim Numer As Long
            Dim Denom As Long
    
            Numer = Num / Arithmetic.GreatestCommonDivisor(Num, Den)
            Denom = Den / Arithmetic.GreatestCommonDivisor(Num, Den)
    
            If Denom = 1 Then
                Return Numer.ToString()
            Else
                Return String.Format("{0}/{1}", Numer, Denom)
            End If
        End Function
    End Class

The Formula

To overload an operator, you must create a Shared method using the following formula:

[ <attrlist> ] Public [ Overloads ] Shared [ Shadows ] [ Widening | Narrowing ] 
Operator operatorsymbol ( operand1 [, operand2 ]) [ As [ <attrlist> ] type ]
    [ statements ]
    [ statements ]
    Return returnvalue
    [ statements ]
End Operator

You can start with the Public access modifier, followed by the Shared keyword. You can use additional keywords and/or mechanisms to control access to the method. You must then use the Operator keyword. This is followed by the actual operator you want to customize. There are rules you must, and suggestions you should, follow:

  • Not all operators need to be customized for all classes. For example, while it would be feasible to add two books to get a new book that includes all the pages on both books and their combined authors, it may not be realistic to multiply two books (to get what?). Therefore, you should select the right operator based on your needs
  • While some operators are always available to be overloaded, some operators have restrictive rules. This means that you cannot just use any operator anyhow
  • Not all operators are overloadable

After the operator, open that parentheses that must always be used on a function. In the parentheses, you will add one or more arguments, depending on the operator. After the closing parenthesis, you must specify a return type. Normally, you should return the class itself. After all, the operator will act on an object of its class type. For this reason, the method should return a value that represents its class.

To end the method, you must use the End Operator expression. In the body of the method, you can implement the behavior and make sure you return a value. After defining the method, you can call it either inside or outside the class.

Overloading an Operator

 

Unary Operators

A unary operator is one that acts on one value. The Visual Basic language provides many unary operators but not all can be overloaded. The unary operarors available for overloading are +, -, Not, IsTrue, IsFalse, and CType.

To overload a unary operator, pass one argument to the parentheses of the method. In the body of the method, perform the desired operation. Here is an example of overloading a unary operator:

Public Class Natural
    Public Number As Integer

    Public Sub New(ByVal N As Integer)
        Number = N
    End Sub

    Public Shared Operator Not(ByVal Value As Natural) As Natural

        Dim Nbr As Integer = Value.Number
        Dim N As Integer = Not Nbr

        Dim Nat As Natural = New Natural(N)

        Return Nat
    End Operator

    Public Overrides Function ToString() As String
        Return Number.ToString()
    End Function
End Class

Here is an example of applying that operator:

Public Module Exercise

    Public Function Main() As Integer
        Dim Nbr As Natural

        Nbr = New Natural(1405)

        MsgBox("The bitwise nagation of " & Nbr.ToString() & " is " & (Not Nbr).ToString())

        Return 0
    End Function

End Module

This would produce:

Overloading a Unary Operator

In the same way, you can overload the other operators.

Binary Arithmetic Operators

A binary operator is one that acts on two values. The values must be of the same type. The Visual Basic language provides a rich set of binary operators. Those used in arithmetics are: +, -, *, /, \, and Mod.

To overloaded a binary arithmetic operator, pass two arguments to the parentheses of the method. The first arguments must be of the type of class in which you are working. The second argument can be another type. Here is an example:

Public Class Natural
    Public Number As Integer

    Public Sub New(ByVal N As Integer)
        Number = N
    End Sub

    Public Shared Operator Not(ByVal Value As Natural) As Natural

        Dim Nbr As Integer = Value.Number
        Dim N As Integer = Not Nbr

        Dim Nat As Natural = New Natural(N)

        Return Nat
    End Operator

    Public Shared Operator +(ByVal Value As Natural, ByVal Add As Integer) As Natural
        Dim Nbr As Integer = Value.Number
        Dim N As Integer = Nbr + Add

        Dim Nat As Natural = New Natural(N)
        Return Nat
    End Operator

    Public Overrides Function ToString() As String
        Return Number.ToString()
    End Function
End Class

Here is an example of using the operator:

Public Module Exercise

    Public Function Main() As Integer
        Dim Nbr As Natural

        Nbr = New Natural(248)

        MsgBox(Nbr.ToString() & " + 35 = " & (Nbr + 35).ToString())

        Return 0
    End Function

End Module

This would produce:

Overloading a Unary Operator

If you want to perform the operations on two similar types of values, then the second argument must be of the same type as the first, which is the class you are using.

 
 
 

ApplicationApplication: Overloading Binary Operators

  1. Access the Rational.vb file and change it as follows:
    Imports Mathematics
    
    Public Class Rational
        Private Num As Long
        Private Den As Long
    
        Public Sub New(ByVal n As Long, ByVal d As Long)
            Num = n
            Den = d
        End Sub
    
        Public Property Numerator() As String
            Get
                Return Num / Arithmetic.GreatestCommonDivisor(Num, Den)
            End Get
            Set(ByVal value As String)
                Num = value
            End Set
        End Property
    
        Public Property Denominator() As String
            Get
                Return Den / Arithmetic.GreatestCommonDivisor(Num, Den)
            End Get
            Set(ByVal value As String)
                Den = value
            End Set
        End Property
    
        Public Shared Operator +(ByVal First As Rational,
                                 ByVal Second As Rational) As Rational
            Dim Top As Long
            Dim Bottom As Long
    
            Top = (First.Numerator * Second.Denominator) +
                  (First.Denominator * Second.Numerator)
            Bottom = First.Denominator * Second.Denominator
    
            Return New Rational(Top, Bottom)
        End Operator
    
        Public Shared Operator -(ByVal First As Rational,
                                 ByVal Second As Rational) As Rational
            Dim Top As Long
            Dim Bottom As Long
    
            Top = (First.Numerator * Second.Denominator) -
                  (First.Denominator * Second.Numerator)
            Bottom = First.Denominator * Second.Denominator
    
            Return New Rational(Top, Bottom)
        End Operator
    
        Public Shared Operator *(ByVal First As Rational,
                                 ByVal Second As Rational) As Rational
            Dim Top As Long
            Dim Bottom As Long
    
            Top = First.Numerator * Second.Numerator
            Bottom = First.Denominator * Second.Denominator
    
            Return New Rational(Top, Bottom)
        End Operator
    
        Public Shared Operator /(ByVal First As Rational,
                                 ByVal Second As Rational) As Rational
            Dim Top As Long
            Dim Bottom As Long
    
            Top = First.Numerator * Second.Denominator
            Bottom = First.Denominator * Second.Numerator
    
            Return New Rational(Top, Bottom)
        End Operator
    
        Public Overrides Function ToString() As String
            Dim Numer As Long
            Dim Denom As Long
    
            Numer = Num / Arithmetic.GreatestCommonDivisor(Num, Den)
            Denom = Den / Arithmetic.GreatestCommonDivisor(Num, Den)
    
            If Denom = 1 Then
                Return Numer.ToString()
            Else
                Return String.Format("{0}/{1}", Numer, Denom)
            End If
        End Function
    End Class
  2. Access the Algebra.vb file and change it as follows:
    Module Algebra
    
        Public Function Main() As Integer
            Dim a, b, c, d As Long
            Dim FirstFraction As Rational = Nothing
            Dim SecondFraction As Rational = Nothing
    
            MsgBox("This program allows you to perform " &
                   "an arithmetic operation on two fractions")
            a = CLng(InputBox("=-= First Fraction =-=" & vbCrLf &
                              "Enter the numerator:"))
            b = CLng(InputBox("=-= First Fraction =-=" & vbCrLf &
                               "Enter the denominator: "))
            c = CLng(InputBox("=-= Second Fraction =-=" & vbCrLf &
                               "Enter the numerator:"))
            d = CLng(InputBox("=-= Second Fraction =-=" & vbCrLf &
                              "Enter the denominator:"))
    
            FirstFraction = New Rational(a, b)
            MsgBox(String.Format("First Fraction:   {0}/{1} => {2}", a, b, FirstFraction))
            SecondFraction = New Rational(c, d)
            MsgBox(String.Format("Second Fraction:  {0}/{1} => {2}", c, d, SecondFraction))
    
            Dim Addition As Rational
            Dim Subtraction As Rational
            Dim Multiplication As Rational
            Dim Division As Rational
    
            Addition = FirstFraction + SecondFraction
            MsgBox(String.Format("Addition: {0}/{1} + {2}/{3} = {4}", a, b, c, d, Addition))
    
            Subtraction = FirstFraction - SecondFraction
            MsgBox(String.Format("Addition: {0}/{1} + {2}/{3} = {4}", a, b, c, d, Subtraction))
    
            Multiplication = FirstFraction * SecondFraction
            MsgBox(String.Format("Addition: {0}/{1} + {2}/{3} = {4}", a, b, c, d, Multiplication))
    
            Division = FirstFraction / SecondFraction
            MsgBox(String.Format("Addition: {0}/{1} + {2}/{3} = {4}", a, b, c, d, Division))
    
            Return 0
        End Function
    
    End Module
  3. To execute the application, on the main menu, click Debug -> Start Debugging
     
    Fractions
  4. Click OK
  5. When requested, enter the first numerator as 128 and press Enter
  6. Enter the first denominator as 54 and press Enter
  7. Enter the second numerator as 88 and press Enter
  8. Enter the second denominator as 36 and press Enter
     
    Fractions
    Fractions
    Fractions
    Fractions
    Fractions
    Fractions

Binary Bitwise Operators

Besides the traditional arithmetic operations, Visual Basic support the ability to add or shift bits in the computer memory. These operators are the bitwise conjunction operator & and its  assignment operator &=, the bitwise disjunction operator | and its assignment operator |=, the bitwise exclusion operator ^ and its assignment operator ^=, the left-shift operator << and its assigment operator <<=, the right-shift operator >> and its assignment operator >>=. When necessary, overload only the primary operator (&, |, ^, <<, >>) and its equivalent assignment operator will be automatically provided by the compiler.

To overloaded a binary operator, pass two arguments to the parentheses of the method. For the two bitwise shift operators, << and >>, the first argument must be the class in which you are working and the second argument must by a constant integer (type int). Here is an example that overloads the left bitwise shifter <<:

Public Class Natural
    Public Number As Integer

    Public Sub New(ByVal N As Integer)
        Number = N
    End Sub

    Public Shared Operator Not(ByVal Value As Natural) As Natural

        Dim Nbr As Integer = Value.Number
        Dim N As Integer = Not Nbr

        Dim Nat As Natural = New Natural(N)

        Return Nat
    End Operator

    Public Shared Operator +(ByVal Value As Natural, ByVal Add As Integer) As Natural
        Dim Nbr As Integer = Value.Number
        Dim N As Integer = Nbr + Add

        Dim Nat As Natural = New Natural(N)
        Return Nat
    End Operator

    Public Shared Operator <<(ByVal Value As Natural, ByVal Shifts As Integer) As Natural
        Dim Nbr As Integer = Value.Number
        Dim N As Integer = (Nbr << Shifts)

        Dim Nat As Natural = New Natural(N)
        Return Nat
    End Operator

    Public Overrides Function ToString() As String
        Return Number.ToString()
    End Function
End Class

Here is an example of using the operator:

Public Module Exercise

    Public Function Main() As Integer
        Dim Nbr As Natural

        Nbr = New Natural(1248)

        MsgBox("Shiftting the bits of " & Nbr.ToString() &
               " to the left by 4 is " & (Nbr << 4).ToString())

        Return 0
    End Function

End Module

This would produce:

Overloading a Bit Shift Operator

For the operators that join or disjoin two series of bits:

  • The first argument must be the class on which you are working. The second argument can be an integer. Here is an example:
    Public Shared Operator And(ByVal Value As Natural,
     			   ByVal Constant As Integer) As Natural
            Dim Result As Integer = Value.Number And Constant
    
            Return New Natural(Result)
    End Operator
    -----------------------------------------------------------------------
    Public Module Exercise
    
        Public Function Main() As Integer
            Dim Nbr As Natural
    
            Nbr = New Natural(286)
    
            MsgBox("286 AND 4075 = " & (Nbr And 4075).ToString())
    
            Return 0
        End Function
    
    End Module
    
    Operator Overloading: And
  • The first argument must be the class on which you are working. The second argument can be a class of the same type as the first argument. Here is an example:
    Public Class Natural
        Public Number As Integer
    
        Public Sub New(ByVal N As Integer)
            Number = N
        End Sub
    
        Public Shared Operator Not(ByVal Value As Natural) As Natural
    
            Dim Nbr As Integer = Value.Number
            Dim N As Integer = Not Nbr
    
            Dim Nat As Natural = New Natural(N)
    
            Return Nat
        End Operator
    
        Public Shared Operator +(ByVal Value As Natural, ByVal Add As Integer) As Natural
            Dim Nbr As Integer = Value.Number
            Dim N As Integer = Nbr + Add
    
            Dim Nat As Natural = New Natural(N)
            Return Nat
        End Operator
    
        Public Shared Operator <<(ByVal Value As Natural, ByVal Shifts As Integer) As Natural
            Dim Nbr As Integer = Value.Number
            Dim N As Integer = (Nbr << Shifts)
    
            Dim Nat As Natural = New Natural(N)
            Return Nat
        End Operator
    
        Public Shared Operator And(ByVal Value As Natural,
                                   ByVal Constant As Integer) As Natural
            Dim Result As Integer = Value.Number And Constant
    
            Return New Natural(Result)
        End Operator
    
        Public Shared Operator And(ByVal Operand1 As Natural,
                                   ByVal Operand2 As Natural) As Natural
            Dim Result As Integer = Operand1.Number And Operand2.Number
    
            Return New Natural(Result)
        End Operator
    
        Public Overrides Function ToString() As String
            Return Number.ToString()
        End Function
    End Class
    ---------------------------------------------------
    Public Module Exercise
    
        Public Function Main() As Integer
            Dim Nbr1 As Natural = New Natural(52)
            Dim Nbr2 As Natural = New Natural(2447)
    
            MsgBox("52 AND 2447 = " & (Nbr1 And Nbr2).ToString())
    
            Return 0
        End Function
    
    End Module

    This would produce:
     
    Operator Overloading: And

In the same way you can overload the other operators.

Comparison Operators

As its name implies, a comparison is used to find out whether one of two values is higher than the other. The values must be of the same type. Comparison operators go in pair. That is, if you want to compare two values for equality, you must also be able to know when they are different. For this reason, if you decide to overload a comparison operator, you must also overload its opposite:

  • If you overload =, you must also overload <> and vice versa
  • If you overload <, you must also overload > and vice versa
  • If you overload <=, you must also overload >= and vice versa
  • If you overload IsTrue, you must also overload IsFalse and vice versa

We know that the Object class is equipped with a method named Equals. That method makes it possible to find out whether one object is equal to another. And since all classes in a Visual Basic application derive from Object, if you decide to overload a couple of comparison operators, you should also override the Equals() method. 

Restricted Operators

Some operators either cannot be overloaded or depend on other operators being overloaded. The following operators cannot be overloaded: =, AddressOf, AndAlso, AsType, GetType, Is, IsNot, New, OrElse, and TypeOf ... Is.

ApplicationApplication: Ending the Lesson

  1. Close your programming environment
  2. When asked whether you want to save, click No
 
 
   
 

Home Copyright © 2010-2016, FunctionX