Chapter 28. Overloading Operators

In Lesson 27 you learned how to overload a class's methods. Visual Basic also lets you overload operators such as + and * to give them new meanings when working with the structures and classes that you create. For example, you could overload the + operator so the program would know how to add a Student object and a Course object. Sometimes that enables you to use a more natural syntax when you're working with objects.

In this lesson, you learn how to overload operators so you can use them to manipulate objects.

Warning

Before you jump into operator overloading, be warned that just because you can overload an operator doesn't mean you should. You should only overload operators in intuitive ways.

For example, it makes sense to overload the + operator so you can add two ComplexNumber objects. It might also make sense to overload + so you can add an item to a purchase order.

It probably doesn't make sense to define + between two Employee objects to return a list of projects that include both employees. You could do that but you probably shouldn't because it would be confusing.

OVERLOADABLE OPERATORS

In Visual Basic, you can overload unary, binary, and logical operators. Table 28-1 summarizes the operators that you can overload.

Table 28.1. TABLE 28-1

TYPE

OPERATORS

Unary

+, -, Not, IsTrue, IsFalse, CType

Binary

+, –, *, /, , ⁁, &, Like, Mod, And, Or, Xor, <<, >>

Comparison

=, <>, <, >, <=, >=

The comparison operators come in pairs. For example, if you overload the < operator, then you must also overload the > operator.

The compound assignment operators (+=, -=, *=, /=, =, &=, ⁁=, <<=, and >>=) are automatically overloaded when you overload the corresponding binary operator. For example, if you overload *, then Visual Basic automatically overloads *=.

The syntax for overloading operators is easiest to understand by looking at examples. The following sections explain how to overload the different types of operators.

UNARY OPERATORS

The following code shows how you can overload the unary operator for the ComplexNumber class:

Public Shared Operator -(ByVal c1 As ComplexNumber) As ComplexNumber
    Return New ComplexNumber(-c1.Real, -c1.Imaginary)
End Operator

The method begins with Public accessibility. The Shared keyword means this operator is shared by all instances of the ComplexNumber class, so you can apply it without using a specific instance of the class. The Operator keyword means the code overloads an operator.

Next comes the operator being overloaded. The parameter list specifies the objects that are involved in the calculation. This example overloads the unary operator, so it involves only one parameter. That parameter is of type ComplexNumber, so that is the class for which this code defines the operator.

The declaration finishes by declaring the operator's return type.

Note that the overloaded operator must be defined inside the parameter's structure or class. In this case, because the parameter is a ComplexNumber, this code must be in the ComplexNumber class.

The code inside this method simply negates the ComplexNumber's real and imaginary parts and returns a new ComplexNumber.

The following code shows how a program might use this operator:

Dim a As New ComplexNumber(1, 2)     '  1 + 2i
Dim b As ComplexNumber = -a          ' −1 - 2i

BINARY OPERATORS

Overloading binary operators is similar to overloading unary operators except the operator takes a second parameter. The first parameter is still the object to which the operator is being applied.

For example, the following code overloads the binary operator to subtract two ComplexNumbers:

Public Shared Operator -(ByVal c1 As ComplexNumber,
 ByVal c2 As ComplexNumber) As ComplexNumber
    Return New ComplexNumber(
        c1.Real - c2.Real,
        c1.Imaginary - c2.Imaginary)
End Operator

The first parameter indicates the object on the left of the sign and the second parameter indicates the object on the right.

Note that the overload must be declared inside a class or structure used by one of the parameters. In this case, because both parameters are ComplexNumbers, this code must be in the ComplexNumber class.

While this example subtracts two ComplexNumbers, the parameters do not need to have the same data types. The following code defines the binary operator for subtracting a Double from a ComplexNumber:

Public Shared Operator -(ByVal c1 As ComplexNumber,
 ByVal re As Double) As ComplexNumber
    Return c1 - New ComplexNumber(re)
End Operator

Note that this is not the same as subtracting a ComplexNumber from a Double. If you want to handle that situation as well, you need the following separate overload:

Public Shared Operator -(ByVal re As Double,
 ByVal c1 As ComplexNumber) As ComplexNumber
    Return New ComplexNumber(re) - c1
End Operator

With these overloads, a program could execute the following code:

Dim a As New ComplexNumber(2, 3)
Dim b As New ComplexNumber(4, 5)

Dim f As ComplexNumber = a - b          ' ComplexNumber - ComplexNumber
Dim g As ComplexNumber = a - 10         ' ComplexNumber - Double
Dim h As ComplexNumber = 10 - a         ' Double - ComplexNumber

Note

The shift operators << and >> are a little different from the other binary operators because the second parameter must always be an integer.

COMPARISON OPERATORS

The comparison operators are simply binary operators that return a Boolean result. The only oddity to these is that they come in pairs. For example, if you define =, then you must also define <>. The pairs are = and <>, < and >, and <= and >=.

The following code shows how you could overload the < and > operators for the ComplexNumber class by comparing the numbers' magnitudes:

' Return the number's magnitude.
Public ReadOnly Property Magnitude() As Double
    Get
        Return (Math.Sqrt(Real * Real + Imaginary * Imaginary))
    End Get
End Property

Public Shared Operator <(ByVal c1 As ComplexNumber,
 ByVal c2 As ComplexNumber) As Boolean
    Return (c1.Magnitude < c2.Magnitude)
End Operator

Public Shared Operator >(ByVal c1 As ComplexNumber,
 ByVal c2 As ComplexNumber) As Boolean
    Return (c1.Magnitude > c2.Magnitude)
End Operator

CTYPE

The CType operator converts a value from one data type to another. You may recall from Lesson 11 that data type conversions can be either widening or narrowing.

A widening conversion converts a value into a new data type that is guaranteed to be able to hold the value without losing any precision. For example, a Long can hold any Integer value, so converting from an Integer to a Long is a widening conversion.

Conversely, not all Long values can fit into an Integer, so converting from a Long to an Integer is a narrowing conversion.

To help Visual Basic understand which kind of conversion you are defining, you must provide one of the keywords Widening or Narrowing when you overload the CType operator.

For example, the following code overloads CType to convert between the Double and ComplexNumber data types:

' Convert between Double and ComplexNumber.
Public Shared Widening Operator CType(ByVal re As Double) As ComplexNumber
    Return New ComplexNumber(re, 0)
End Operator

Public Shared Narrowing Operator CType(ByVal c1 As ComplexNumber) As Double
    Return c1.Magnitude
End Operator

The first overload converts from Double to ComplexNumber and the second converts from ComplexNumber to Double.

Visual Basic will use CType to convert from one type to another if it can to perform other operations that are not directly defined. For example, suppose you define the + operator for two ComplexNumbers and you also define the CType operator to convert from Double to ComplexNumber. In that case, the following code will work even though you haven't defined + for Doubles and ComplexNumbers:

Dim a As New ComplexNumber(1, 2)
Dim b As Double = 3
Dim c As ComplexNumber = a + b

When it reaches the third line, the program doesn't know how to add the ComplexNumber a and the Double b. However, it does know how to use CType to make a widening conversion to promote b to a ComplexNumber. It does so and adds the ComplexNumbers.

This very convenient feature of CType enables you to skip defining a huge number of operators.

TRY IT

In this Try It, you extend the ComplexNumber class you built in Lesson 27, Exercise 1. That version of the class included methods such as AddTo and SubtractFrom to perform simple operations. Now you'll replace those cumbersome methods with overloaded +, -, *, and unary operators.

Note

You can download the code and resources for this Try It from the book's web page at www.wrox.com or www.vb-helper.com/24hourvb.html. You can find them in the Lesson28 folder of the download.

Lesson Requirements

In this lesson:

  • Copy the ComplexNumber program you built for Lesson 27, Exercise 1 (or download Lesson 27's version from the book's web site). Remove the ComplexNumber class's AddTo, MultiplyBy, and SubtractFrom methods.

  • Give the class new overloaded operators to handle these cases:

    • -ComplexNumber

    • ComplexNumber + ComplexNumber

    • ComplexNumber * ComplexNumber

    • ComplexNumber - ComplexNumber

    • CType between Double and ComplexNumber

  • Revise the main form's code to use the new operators.

Hints

  • You can use operators to define other operators. For example, if you define the unary operator, then the following two operations have the same result:

    ComplexNumber - ComplexNumber
    ComplexNumber + -ComplexNumber

Step-by-Step

  • Copy the ComplexNumber program you built for Lesson 27, Exercise 1 (or download Lesson 27's version from the book's web site). Remove the ComplexNumber class's AddTo, MultiplyBy, and SubtractFrom methods.

    1. This is reasonably straightforward.

  • Give the class new overloaded operators to handle these cases:

    • -ComplexNumber

    • ComplexNumber + ComplexNumber

    • ComplexNumber * ComplexNumber

    • ComplexNumber - ComplexNumber

    • CType between Double and ComplexNumber

    1. You can use code similar to the following:

      ' Unary -.
      Public Shared Operator -(ByVal c1 As ComplexNumber) As ComplexNumber
          Return New ComplexNumber(-c1.Real, -c1.Imaginary)
      End Operator
      
      ' Binary +.
      Public Shared Operator +(ByVal c1 As ComplexNumber,
       ByVal c2 As ComplexNumber) As ComplexNumber
          Return New ComplexNumber(
              c1.Real + c2.Real,
              c1.Imaginary + c2.Imaginary)
      End Operator
      
      ' Binary *.
      Public Shared Operator *(ByVal c1 As ComplexNumber,
       ByVal c2 As ComplexNumber) As ComplexNumber
          Return New ComplexNumber(
              c1.Real * c2.Real - c1.Imaginary * c2.Imaginary,
              c1.Real * c2.Imaginary + c1.Imaginary * c2.Real)
      End Operator
      
      ' Binary -.
      Public Shared Operator -(ByVal c1 As ComplexNumber,
       ByVal c2 As ComplexNumber) As ComplexNumber
          Return New ComplexNumber(
      c1.Real - c2.Real,
              c1.Imaginary - c2.Imaginary)
      End Operator
      
      ' Convert between Double and ComplexNumber.
      Public Shared Widening Operator CType(ByVal re As Double) _
       As ComplexNumber
          Return New ComplexNumber(re, 0)
      End Operator
      
      Public Shared Narrowing Operator CType(ByVal c1 As ComplexNumber) _
       As Double
          Return c1.Magnitude
      End Operator
      
      ' Return the number's magnitude.
      Public ReadOnly Property Magnitude() As Double
          Get
              Return (Math.Sqrt(Real * Real + Imaginary * Imaginary))
          End Get
      End Property
  • Revise the main form's code to use the new operators.

    1. You can use code similar to the following:

      ' Perform the calculations.
      Private Sub btnCalculate_Click() Handles btnCalculate.Click
          Dim a As New ComplexNumber(
              Double.Parse(txtRealA.Text),
              Double.Parse(txtImaginaryA.Text))
          Dim b As New ComplexNumber(
              Double.Parse(txtRealB.Text),
              Double.Parse(txtImaginaryB.Text))
      
          Dim aPlusB As ComplexNumber = a + b
          txtAplusB.Text = aPlusB.ToString
      
          Dim aMinusB As ComplexNumber = a - b
          txtAminusB.Text = aMinusB.ToString
      
          Dim aTimesB As ComplexNumber = a * b
          txtAtimesB.Text = aTimesB.ToString
      
          Dim minusA As ComplexNumber = -a
          txtMinusA.Text = minusA.ToString
      End Sub
      
      ' Perform the calculations with a real number.
      Private Sub btnCalculateRealOnly_Click() _
       Handles btnCalculateRealOnly.Click
          Dim a As Double = Double.Parse(txtRealOnly.Text)
          Dim b As New ComplexNumber(
              Double.Parse(txtRealB.Text),
              Double.Parse(txtImaginaryB.Text))
      Dim aPlusB As ComplexNumber = b + a
          txtAplusB.Text = aPlusB.ToString
      
          Dim aMinusB As ComplexNumber = a - b
          txtAminusB.Text = aMinusB.ToString
      
          Dim aTimesB As ComplexNumber = a * b
          txtAtimesB.Text = aTimesB.ToString
      
          Dim minusA As Double = -a
          txtMinusA.Text = minusA.ToString
      End Sub

Note

Please select Lesson 28 on the DVD to view the video that accompanies this lesson.

EXERCISES

  1. Copy the complex number program you built in this lesson's Try It and overload the ComplexNumber class's / operator to perform division using this equation:

    Equation 28.1. 

    EXERCISES

    Change the main program to calculate A / B and display the results. Verify these calculations:

    • (10+11i) / (3+2i) = 4 + 1i

    • (15+24i) / 3 = 5 + 8i

    • 4 / (1+1i) = 2 - 2i

Note

You can find solutions to this lesson's exercises in the Lesson28 folder inside the download available on the book's web site at www.wrox.com or www.vb-helper.com/24hourvb.html.

EXERCISES
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset