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.
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.
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 |
|
Binary |
|
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.
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
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
The shift operators <<
and >>
are a little different from the other binary operators because the second parameter must always be an integer.
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
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.
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.
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.
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.
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
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.
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
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.
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
Please select Lesson 28 on the DVD to view the video that accompanies this lesson.
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:
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
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
.