«^»
5.8. A class type for representing 2D points

Here is a class type that can be used for representing 2D points:

0037: Public Class Point
0038:     Private iX As Integer
0039:     Private iY As Integer
0040:     Public Sub New(ByVal pX As Integer, ByVal pY As Integer)
0041:         iX = pX
0042:         iY = pY
0043:     End Sub
0044:     Public Property X() As Integer
0045:         Get
0046:             Return iX
0047:         End Get
0048:         Set(ByVal Value As Integer)
0049:             iX = Value
0050:         End Set
0051:     End Property
0052:     Public Function Distance() As Double
0053:         Return Math.Sqrt(iX * iX + iY * iY)
0054:     End Function
0055:     Public Overloads Overrides Function Equals(ByVal pObject As Object) As Boolean
0056:         If (pObject Is Nothing Or Not (Me.GetType() Is pObject.GetType())) Then
0057:             Return False
0058:         End If
0059:         Dim tPoint As Point = DirectCast(pObject, Point)
0060:         Return Me.iX = tPoint.iX And Me.iY = tPoint.iY
0061:     End Function
0062:     Public Overrides Function ToString() As String
0063:         Return iX & ":" & iY
0064:     End Function
0065: End Class

This class declaration needs to be put in a file called Point.vb.

In Visual Studio.NET, you add a new class (called Point) to a project by selecting Add New Item from the File menu, selecting the Class icon, changing the contents of the textbox to Point.vb, and clicking on Open.

Having created the class Point, how do we use it in a program? How do we create objects of this class, and use them?

Well, the class Point provides a constructor. It is shown on lines 40 to 43. So, in a program (e.g., Module1), an instance of the Point class can be created by:

0068:         Dim tPoint As Point = New Point(100, 200)

This produces:

The class Point also provides an instance method called ToString. So in our program we can call ToString as follows:

0069:         Dim tPointString As String = tPoint.ToString()
0070:         Console.WriteLine(tPointString)

This will output:

100:200

However, if a class declares a method called ToString, the ToString method will be called if we pass an object of that class to Write/WriteLine. So the above two statements can be abbreviated to:

0071:         Console.WriteLine(tPoint)

When you produce a class, it is very useful to provide a method called ToString.

In the following statements:

0072:         Dim tDistance As Double = tPoint.Distance()
0073:         Console.WriteLine(tDistance)

there is a call of an instance method called Distance. This will output:

223.606797749979

Suppose we now execute the statements:

0074:         Dim tAnotherPoint As Point = tPoint
0075:         Console.WriteLine(tAnotherPoint)

we will get the output:

100:200

We now have:

i.e., both variables are pointing to the same object.

This can be tested using the Is operator:

0076:         Console.WriteLine("Is: " & (tPoint Is tAnotherPoint))

This outputs:

Is: True

The class Point also provides an instance method called Equals. This can be called as follows:

0077:         Console.WriteLine("Equals: " & (tPoint.Equals(tAnotherPoint)))

This outputs:

Equals: True

If we create another point that happens to have the same value as tPoint then Is will return False whereas Equals will return True. So the statements:

0078:         Dim tClonePoint As Point = New Point(100, 200)
0079:         Console.WriteLine("Is: " & (tPoint Is tClonePoint))
0080:         Console.WriteLine("Equals: " & (tPoint.Equals(tClonePoint)))

output:

Is: False
Equals: True

Whenever you produce a class, it is important to provide a method called Equals that can be used to test whether two objects of that class have the same value.

In another demonstration that shows tPoint and tAnotherPoint are pointing to the same object, consider:

0081:         tAnotherPoint.X = 42
0082:         Console.WriteLine(tPoint.X)

These statements output:

42

Note: in the above declaration of the Point class, the iX and iY fields have been marked as Private. This means that a client of the class Point (such as Module1) is not allowed to access the iX and iY fields of any object. Indeed, if Module1 contains a statement like:

tAnotherPoint.iX = 42
it will not compile.

Instead, if it is necessary to allow a client to inspect/alter the value of a field, the class should provide a Property. In the above declaration of the Point class, a Property called X has been introduced that permits the value of the iX field to be got or set. By using a Property, you know that all accesses to the field will be done through the code of the Property. So you retain control. This is useful, e.g.:

If we now change the iX field of tClonePoint:

0083:         tClonePoint.X = 27
0084:         Console.WriteLine(tPoint.X)

the output:

42

again demonstrates that tPoint and tClonePoint are pointing to different objects.