Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(ebook) Visual Studio .NET Mastering Visual Basic.pdf
Скачиваний:
136
Добавлен:
17.08.2013
Размер:
15.38 Mб
Скачать

340 Chapter 8 BUILDING CUSTOM CLASSES

The statements of Listing 8.9 will produce the following output:

They’re equal

They’re equal

The two variables are initially equal. No surprise. After modifying one of the obj2 variable’s properties, however, they’re still equal, because obj2 points to obj1. Every time we change obj2, obj1 also changes. That’s because we’ve made obj1 point to obj2. They both point to the same object (or instance of the class), and you can access this object through either class.

Comment out the line that sets obj2 equal to obj1. Now, they’re not equal, even if you set all their fields to the same values. They don’t reference the same object, and it’s possible to set their properties differently.

In the following section, we’ll add an Equals method that checks for value equality (as opposed to reference equality) by comparing the values of the properties of the two instances.

Customizing Default Members

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 provide your custom implementation for these members; this is what we’re going to do in this section. You already know how to do this. Your custom ToString method must be 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

It’s that simple. The Overrides keyword tells the compiler that this implementation overwrites the default implementation of the class. Ours is a very 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: “ & tBDate.ToString)

tBDate is a local variable in the class’s module, and you can use its value in any way you see fit in your code. The value of the local variable tBDate is the current value of the BDate property of the current instance of the class.

When called through different variables, the ToString method will report different values. Let’s say you’ve created and initialized two instances of the Minimal class with the following statements:

Dim obj1 As New Minimal()

Obj1.Bdate = #1/1/1963#

Dim obj2 As New Minimal()

Obj2.Bdate = #12/31/1950#

Console.WriteLine(obj1.ToString)

Console.WriteLine(obj2.ToString)

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

BUILDING THE MINIMAL CLASS 341

The last two statements will print the following lines on the Output window:

MINIMAL: 1963-01-01 00:00:00

MINIMAL: 1950-12-31 00:00:00

The Equals method exposed by most of the built-in objects, however, 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

If you execute these statements, a message box will pop up. The two variables point to different objects (i.e., different instances of the same class), but the two objects are equal. 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. 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 of 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. You may even compare internal variables that are not exposed as properties to decide about the equality. In the Minimal class, for example, you may decide to compare the birth dates and return True if they’re equal. Listing 8.10 is the implementation of a possible custom Equals method for the Minimal class.

Listing 8.10: A Custom Equals Method

Public Overloads Function Equals(ByVal obj As Object) As Boolean

Dim O As Minimal = CType(obj, Minimal)

If O.BDate = tBDate Then

Equals = True

Else

Equals = False

End If

End Function

Notice that the Equals method is prefixed with the Overloads keyword, not the Overrides keyword. To test the new Equals method, place a new button on the form and insert the statements of Listing 8.11 in its Click event handler.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

342 Chapter 8 BUILDING CUSTOM CLASSES

Listing 8.11: 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.property1 = “object1”

O2.property1 = “OBJECT2”

If O1.Equals(O2) Then

MsgBox(“They’re equal”)

End If

If you run the application, you’ll see the message confirming that the two objects are equal, despite the fact that their property1 properties were set to different values. The BDate property is the same, and this is the only setting 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 in determining when two objects are equal. It’s customary to compare the values of all the properties of the two objects in the Equals function and return True if they’re all the same. You can modify the code of the custom Equals function to take into consideration the other properties.

Know What You’re Comparing

The Equals method shown in Listing 8.10 assumes that the object you’re trying to compare to the current instance of the class is of the same type. Since you can’t rely on developers to catch all their mistakes, you should know what you’re comparing before you actually do the comparison. A more robust implementation of the Equals method is shown in Listing 8.12.

Listing 8.12: A More Robust Equals Method

Public Overloads Function Equals(ByVal obj As Object) As Boolean

Dim O As New Minimal()

Try

O = CType(obj, Minimal)

Catch typeExc As InvalidCastException

Throw typeExc

Exit Function

End Try

If O.BDate = tBDate Then

Equals = True

Else

Equals = False

End If

End Function

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

BUILDING THE MINIMAL CLASS 343

Note Note that the custom Equals method throws the same exception it receives from the CType() function. This is a little different from creating and throwing a new custom exception, as we did in the Age property’s code.

Custom Enumerations

Let’s add a little more complexity to our class. Since we’re storing dates of birth to our class, we can classify persons according to their age. Instead of using literals to describe the various age groups, we’ll use an enumeration, with the following group names:

Public Enum AgeGroup

Baby

Child

Teenager

Adult

Senior

Overaged

End Enum

These statements must appear outside any procedure in the class, and we usually place them at the beginning of the file, right after the declaration of the Class. The enumeration is a list of integer values, each one mapped to a name. In our example, the name Baby corresponds to 0, the name Child corresponds to 1, and so on. You don’t really care about the actual values of the names, because the very reason for using enumerations is to replace numeric constants with more meaningful names. You’ll see shortly how enumerations are used both in the class and the calling application.

Now add to the class the GetAgeGroup method (Listing 8.13), which returns the name of the group to which the person represented by an instance of the Minimal class belongs. The name of the group is a member of the AgeGroup enumeration.

Listing 8.13: Using an Enumeration

Public Function GetAgeGroup() As AgeGroup

Dim group As AgeGroup

Select Case tAge

Case Is < 5 : Return (group.Baby)

Case Is < 12 : Return (group.Child)

Case Is < 21 : Return (group.Teenager)

Case Is < 65 : Return (group.Adult)

Case Is < 100 : Return (group.Senior)

Case Else : Return (group.Overaged)

End Select

End Function

First, we declare a variable of the AgeGroup type. As you can see, the members of the AgeGroup enumeration become properties of the group variable. The advantage of using enumerations is that you can manipulate meaningful names instead of numeric constants. This makes your code less prone to errors and far easier to understand.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com