Section 2.7. Use Operators with Custom Objects


2.7. Use Operators with Custom Objects

Every VB programmer is familiar with the arithmetic operators for addition (+), subtraction (-), division (/), and multiplication (*). Ordinarily, these operators are reserved for .NET numeric types, and have no meaning when used with other objects. However, in VB .NET 2.0 you can build objects that support all of these operators, as well as the operators used for logical operations and implicit conversion). This technique won't make sense for business objects, but it is extremely handy if you need to model mathematical structures such as vectors, matrixes, complex numbers, oras demonstrated in the following examplefractions.


Note: Tired of using clumsy syntax like ObjA.Subtract(ObjB) to perform simple operations on your custom objects? With VB's support for operator overloading, you can manipulate your objects as easily as ordinary numbers.

2.7.1. How do I do that?

To overload an operator in Visual Basic 2005, you need to create a special operator method in your class (or structure). This method must be declared with the keywords Public Shared Operator, followed by the symbol for the operator (e.g., +).


Tip: To overload an operator simply means to define what an operator does when used with a specific type of object. In other words, when you overload the + operator for a Fraction class, you tell .NET what to do when your code adds two Fraction objects together.

For example, here's an operator method that adds support for the addition (+) operator:

Public Shared Operator+(objA As MyClass, objB as MyClass) As MyClass     ' (Code goes here.) End Operator

Every operator method accepts two parameters, which represent the values on either side of the operator. Depending on the class and the operator, order may be important (as it is for division).

Once you've defined an operator, the VB compiler will call your code when it executes a statement that uses the operator with your class. For example, the compiler changes code like this:

ObjC = ObjA + ObjB

into this:

ObjC = MyClass.Operator+(ObjA, ObjB)

Example 2-3 shows how you can overload the Visual Basic arithmetic operators used to handle Fraction objects. A Fraction consists of two portions: a numerator and a denominator (known colloquially as "the top part and the bottom part"). The Fraction code overloads the +, -, *, and / operators, allowing you to perform fractional calculations without converting your numbers to decimals and losing precision.

Example 2-3. Overloading arithmetic operators in the Fraction class
Public Structure Fraction          ' The two parts of a fraction.     Public Denominator As Integer     Public Numerator As Integer          Public Sub New(ByVal numerator As Integer, ByVal denominator As Integer)         Me.Numerator = numerator         Me.Denominator = denominator     End Sub          Public Shared Operator +(ByVal x As Fraction, ByVal y As Fraction) _       As Fraction         Return Normalize(x.Numerator * y.Denominator + _           y.Numerator * x.Denominator, x.Denominator * y.Denominator)     End Operator          Public Shared Operator -(ByVal x As Fraction, ByVal y As Fraction) _       As Fraction         Return Normalize(x.Numerator * y.Denominator - _           y.Numerator * x.Denominator, x.Denominator * y.Denominator)     End Operator          Public Shared Operator *(ByVal x As Fraction, ByVal y As Fraction) _       As Fraction         Return Normalize(x.Numerator * y.Numerator, _           x.Denominator * y.Denominator)     End Operator          Public Shared Operator /(ByVal x As Fraction, ByVal y As Fraction) _       As Fraction         Return Normalize(x.Numerator * y.Denominator, _           x.Denominator * y.Numerator)     End Operator          ' Reduce a fraction.     Private Shared Function Normalize(ByVal numerator As Integer, _       ByVal denominator As Integer) As Fraction         If (numerator <> 0) And (denominator <> 0) Then             ' Fix signs.             If denominator < 0 Then                 denominator *= -1                 numerator *= -1             End If                  Dim divisor As Integer = GCD(numerator, denominator)             numerator \= divisor             denominator \= divisor         End If              Return New Fraction(numerator, denominator)     End Function          ' Return the greatest common divisor using Euclid's algorithm.     Private Shared Function GCD(ByVal x As Integer, ByVal y As Integer) _       As Integer         Dim temp As Integer              x = Math.Abs(x)         y = Math.Abs(y)         Do While (y <> 0)             temp = x Mod y             x = y             y = temp         Loop              Return x     End Function          ' Convert the fraction to decimal form.     Public Function GetDouble( ) As Double         Return CType(Me.Numerator, Double) / _           CType(Me.Denominator, Double)     End Function          ' Get a string representation of the fraction.     Public Overrides Function ToString( ) As String         Return Me.Numerator.ToString & "/" & Me.Denominator.ToString     End Function      End Structure

The console code shown in Example 2-4 puts the fraction class through a quirk-and-dirty test. Thanks to operator overloading, the number remains in fractional form, and precision is never lost.

Example 2-4. Testing the Fraction class
Module FractionTest          Sub Main( )         Dim f1 As New Fraction(2, 3)         Dim f2 As New Fraction(1, 4)              Console.WriteLine("f1 = " & f1.ToString( ))         Console.WriteLine("f2 = " & f2.ToString( ))              Dim f3 As Fraction         f3 = f1 + f2     ' f3 is now 11/12         Console.WriteLine("f1 + f2 = " & f3.ToString( ))              f3 = f1 / f2     ' f3 is now 8/3         Console.WriteLine("f1 / f2 = " & f3.ToString( ))              f3 = f1 - f2     ' f3 is now 5/12         Console.WriteLine("f1 - f2 = " & f3.ToString( ))              f3 = f1 * f2     ' f2 is now 1/6         Console.WriteLine("f1 * f2 = " & f3.ToString( ))     End Sub      End Module

When you run this application, here's the output you'll see:

f1 = 2/3 f2 = 1/4 f1 + f2 = 11/12 f1 / f2 = 8/3 f1 - f2 = 5/12 f1 * f2 = 1/6

Usually, the parameters and the return value of an operator method use the same type. However, there's no reason you can't create more than one version of an operator method so your object can be used in expressions with different types.

2.7.2. What about...

...using operator overloading with other types? There are a number of classes that are natural candidates for operator overloading. Here are some good examples:

  • Mathematical classes that model vectors, matrixes, complex numbers, or tensors.

  • Money classes that round calculations to the nearest penny, and support different currency types.

  • Measurement classes that have irregular units, like inches and feet.

2.7.3. Where can I learn more?

For more of the language details behind operator overloading and all the operators that you can overload, refer to the "Operator procedures" index entry in the MSDN Help.



Visual Basic 2005(c) A Developer's Notebook
Visual Basic 2005: A Developers Notebook
ISBN: 0596007264
EAN: 2147483647
Year: 2006
Pages: 123

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net