As you recall, when you created the Minimal class for the first time, before adding any code, the class already exposed a few members— the default members, such as the ToString method (which returns the name of the class) and the Equals method (which compares two objects for reference equality). You can (and should) provide your custom implementation for these members; this is what we’re going to do in this section.
Customizing the ToString Method
The custom ToString method is implemented as a Public function, and it must override the default implementation. The implementation of a custom ToString method is shown next:
Public Overrides Function ToString() As String
Return "The infamous Minimal class"
End Function
Code language: VB.NET (vbnet)
As soon as you enter the keyword Overrides, the editor will suggest the names of the three members you can override: ToString, Equals, and GetHashCode. Select the ToString method, and the editor will insert a default implementation for you. The default implementation returns the string MyBase.ToString. This is the default implementation. (You’ll see later in this chapter what the MyBase keyword is; it basically references the default class implementation.) Just replace the statement inserted by the editor with the one shown in the preceding statement. It’s that simple.
The Overrides keyword tells the compiler that this implementation overwrites the default implementation of the class. The original method’s code isn’t exposed, and you can’t revise it. The Overrides keyword tells the compiler to ‘‘hide’’ the original implementation and use your custom ToString method instead. After you override a method in a class, the application using the class can no longer access the original method. Ours is a simple method, but you can return any string you can build in the function. For example, you can incorporate the value of the BDate property in the string:
Return("MINIMAL: " & m_BDate.ToShortDateString)
Code language: VB.NET (vbnet)
The value of the local variable m_BDate is the value of the BDate property of the current instance of the class. Change the BDate property, and the ToString method will return a different string. When called through different variables, the ToString method will report different values. Let’s say that you created and initialized two instances of the Minimal class by using the following statements:
Dim obj1 As New Minimal()
Obj1.Bdate = #1/1/1963#
Dim obj2 As New Minimal()
Obj2.Bdate = #12/31/1950#
Debug.WriteLine(obj1.ToString)
Debug.WriteLine(obj2.ToString)
Code language: VB.NET (vbnet)
The last two statements will print the following lines in the Output window:
MINIMAL: 1963-01-01
MINIMAL: 1950-12-31
Code language: VB.NET (vbnet)
Customizing the Equals Method
The Equals method exposed by most of the built-in objects can compare values, not references. Two Rectangle objects, for example, are equal if their dimensions and origins are the same. The following two rectangles are equal:
Dim R1 As New Rectangle(0, 0, 30, 60)
Dim R2 As New Rectangle
R2.X = 0
R2.Y = 0
R2.Width = 30
R2.Height = 60
If R1.Equals(R2) Then
MsgBox("The two rectangles are equal")
End If
Code language: VB.NET (vbnet)
If you execute these statements, a message box confirming the equality of the two objects will pop up. The two variables point to different objects (that is, different instances of the same class), but the two objects are equal, because they have the same origin and same dimensions. The Rectangle class provides its own Equals method, which knows how to compare two Rectangle objects. If your class doesn’t provide a custom Equals method, all the compiler can do is compare the objects referenced by the two variables of the specific type. In the case of our Minimal class, the Equals method returns True if the two variables point to the same object (which is the same instance of the class). If the two variables point to two different objects, the default Equals method will return False, even if the two objects are equal.
You’re probably wondering what makes two objects equal. Is it all their properties or perhaps some of them? Two objects are equal if the Equals method says so. You should compare the objects in a way that makes sense, but you’re in no way limited as to how you do this. In a very specific application, you might decide that two rectangles are equal because they have the same area, or perimeter, regardless of their dimensions and origin, and override the Rectangle object’s Equals method. In the Minimal class, for example, you might decide to compare the birth dates and return True if they’re equal. Listing 6.9 is the implementation of a possible custom Equals method for the Minimal class.
Listing 6.9: A CustomEquals Method
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Dim O As Minimal = CType(obj, Minimal)
If O.BDate = m_BDate Then
Equals = True
Else
Equals = False
End If
End Function
Code language: VB.NET (vbnet)
Notice that the Equals method is prefixed with the Overrides keyword, which tells the compiler to use our custom Equals method in the place of the original one. To test the new Equals method, place a new button on the form and insert the statements of Listing 6.10 in its Click event handler.
Listing 6.10: Testing the Custom Equals Method
Dim O1 As New Minimal
Dim O2 As New Minimal
O1.BDate = #3/1/1960#
O2.BDate = #3/1/1960#
O1.strProperty = "object1"
O2.strProperty = "OBJECT2"
If O1.Equals(O2) Then
MsgBox("They're equal")
End If
Code language: VB.NET (vbnet)
If you run the application, you’ll see the message confirming that the two objects are equal, despite the fact that their strProperty properties were set to different values. The BDate property is the same, and this is the only setting that the Equals method examines. So, it’s up to you to decide which properties fully and uniquely identify an object and to use these properties to determine when two objects are equal. In a class that represents persons, you’d probably use Social Security numbers, or a combination of names and birth dates. In a class that represents cars, you’d use the maker, model, and year, and so on.
Know What You Are Comparing
The Equals method shown in Listing 6.10 assumes that the object you’re trying to compare to the current instance of the class is of the same type. Because you can’t rely on developers to catch all their mistakes, you should know what you’re comparing before you attempt to perform the comparison. A more-robust implementation of the Equals method is shown in Listing 6.11. This implementation tries to convert the argument of the Equals method to an object of the Minimal type and then compares it to the current instance of the Minimal class. If the conversion fails, an InvalidCastException is thrown and no comparison is performed.
Listing 6.11: A More-Robust Equals Method
Public Overrides Function Equals(ByVal obj As Object) As Boolean
Dim O As New Minimal()
Try
O = DirectCast(obj, Minimal)
Catch typeExc As InvalidCastException
Throw typeExc
Exit Function
End Try
If O.BDate = m_BDate Then
Equals = True
Else
Equals = False
End If
End Function
Code language: VB.NET (vbnet)
The Is Operator
The equals ( = ) operator can be used in comparing all built-in objects. The following statement is quite valid, as long as the R1 and R2 variables were declared of the Rectangle type:
If R1 = R2 Then
MsgBox("The two rectangles are equal")
End If
Code language: VB.NET (vbnet)
This operator, however, can’t be used with the Minimal custom class. Later in this chapter, you’ll learn how to customize operators in your class. In the meantime, you can use only the Is operator, which compares for reference equality (whether the two variables reference the same object), and the Equals method. If the two variables R1 and R2 point to the same object, the following statement will return True:
If obj1 Is obj2 Then
MsgBox("The two variables reference the same object")
End If
Code language: VB.NET (vbnet)
The Is operator tells you that the two variables point to a single object. There’s no comparison here; the compiler simply figures out whether they point to same object in memory. It will return True if a statement such as the following has been executed before the comparison:
obj2 = obj1
Code language: VB.NET (vbnet)
If the Is operator returns True, there’s only one object in memory and you can set its properties through either variable.