Section 9.2. Encapsulating Data with Properties

   

9.2 Encapsulating Data with Properties

It is generally desirable to designate the member variables of a class as private (using the Private keyword). This means that only member methods of that class can access their value. You make member variables private to support data hiding , which is part of the encapsulation of a class.

Object-oriented programmers are told that member variables should be private. That is fine, but how do you provide access to this data to your clients ? The answer for VB.NET programmers is properties.

Properties allow clients to access class state as if they were accessing member fields directly, while actually implementing that access through a class method.

This is ideal. The client wants direct access to the state of the object. The class designer, however, wants to hide the internal state of the class in class fields, and provide indirect access through a method. The property provides both: the illusion of direct access for the client, the reality of indirect access for the class developer.

By decoupling the class state from the method that accesses that state, the designer is free to change the internal state of the object as needed. When the Time class is first created, the Hour value might be stored as a member variable. When the class is redesigned, the Hour value might be computed, or retrieved from a database. If the client had direct access to the original Hour member variable, the change to computing the value would break the client. By decoupling and forcing the client to go through a property, the Time class can change how it manages its internal state without breaking client code.

In short, properties provide the data hiding required by good object-oriented design. Example 9-2 creates a property called Hour, which is then discussed in the paragraphs that follow.

It is a convention in VB.NET to give your private member variables names with a prefix to distinguish them from the property name . For example, you might prefix every member variable with the letter m (for member), thus mMinute and mHour. You are then free to use the unprefixed version (Hour and Minute) for the property. By convention, properties are named with Pascal case (first letters are uppercase).

Example 9-2. Properties
 Option Strict On Imports System Public Class Time    ' private member variables    Private mYear As Integer    Private mMonth As Integer    Private mDate As Integer    Private mHour As Integer    Private mMinute As Integer    Private mSecond As Integer    Property Hour( ) As Integer       Get          Return mHour       End Get       Set(ByVal Value As Integer)          mHour = Value       End Set    End Property    ' public accessor methods    Public Sub DisplayCurrentTime( )       Console.WriteLine( _       "{0}/{1}/{2} {3}:{4}:{5}", _       mMonth, mDate, mYear, mHour, mMinute, mSecond)    End Sub 'DisplayCurrentTime    ' constructors    Public Sub New(ByVal dt As System.DateTime)       mYear = dt.Year       mMonth = dt.Month       mDate = dt.Date       mHour = dt.Hour       mMinute = dt.Minute       mSecond = dt.Second    End Sub 'New    Public Sub New( _    ByVal mYear As Integer, _    ByVal mMonth As Integer, _    ByVal mDate As Integer, _    ByVal mHour As Integer, _    ByVal mMinute As Integer, _    ByVal mSecond As Integer)       Me.mYear = mYear       Me.mMonth = mMonth       Me.mDate = mDate       Me.mHour = mHour       Me.mMinute = mMinute       Me.mSecond = mSecond    End Sub 'New End Class 'Time Module Module1    Sub Main( )       Dim currentTime As System.DateTime = System.DateTime.Now       Dim time1 As New Time(currentTime)       time1.DisplayCurrentTime( )       'extract the hour to a local variable       Dim theHour As Integer = time1.Hour       'display the local variable       Console.WriteLine("Retrieved the hour: {0}", _        theHour)       'add one to the local variable       theHour += 1       'write the time back to the object       time1.Hour = theHour       'display the result       Console.WriteLine("Updated the hour: {0}", _        time1.Hour)    End Sub End Module 
  Output:  5/1/2002 8:56:59 Retrieved the hour: 8 Updated the hour: 9 

You create a property with this syntax:

 Property   Identifier   ( ) As   Type   Get   statements       End Get      Set(ByVal Value As   Type   )   statements   End Set End Property 

If you create the property in VS.NET however, the editor will provide extensive help with the syntax. For example, once you type:

 Property Minute As Integer 

the IDE will reformat your property as follows :

 Property Minute( ) As Integer    Get        End Get    Set(ByVal Value As Integer)        End Set End Property 

In Example 9-2, Hour is a property. Its declaration creates two accessors: Get and Set .

 Property Hour( ) As Integer    Get       Return mHour    End Get    Set(ByVal Value As Integer) mHour = Value    End Set End Property 

Each accessor has an accessor-body that does the work of retrieving and setting the property value. The property value might be stored in a database (in which case the accessor would do whatever work is needed to interact with the database), or it might just be stored in a private member variable (in this case, mHour):

 Private mHour As Integer 

9.2.1 The Get Accessor

The body of the Get accessor is similar to a class method that returns an object of the type of the property. In Example 9-2, the accessor for the Hour property is similar to a method that returns an integer. It returns the value of the private member variable mHour in which the value of the property has been stored:

 Get    Return mHour End Get 

In this example, the value of mHour is returned, but you could just as easily retrieve an integer value from a database or compute it on the fly.

Whenever you reference the property (other than to assign to it), the Get accessor is invoked to read the value of the property. For example, in the following code the value of the Time object's Hour property is assigned to a local variable. What actually happens is that the Get accessor is called, which returns the value of the Hour member variable, and that value is assigned to the local variable named theHour.

 Dim time1 As New Time(currentTime)  Dim theHour As Integer = time1.Hour  

9.2.2 The Set Accessor

The Set accessor sets the value of a property. Set has an implicit parameter, Value , that represents the assigned value. That is, when you write:

 Minute = 5 

the compiler passes the value you are assigning (5) to the Set statement as the Value parameter. You can then set the member variable to that value using the keyword:

 mMinute = Value 

The advantage of this approach is that the client can interact with the properties directly, without sacrificing the data hiding and encapsulation sacrosanct in good object-oriented design.

9.2.3 ReadOnly and WriteOnly Properties

At times you may want to create a property that allows you to retrieve a value but not to set it. You can mark your property ReadOnly , as in the following:

 ReadOnly Property Hour( ) As Integer 

Doing so allows you (and forces you) to leave out the Set statement in your property. If you do add a Set statement, the compiler will complain with the message:

 Properties declared 'ReadOnly' cannot have a 'Set' 

If you leave out the Set statement and then try to assign to the property, the compiler will complain with the message:

 Property 'Hour' is 'ReadOnly' 

In short, marking the property ReadOnly enlists the compiler in enforcing that you cannot use that property to set a value.

Similarly, you can mark a property WriteOnly :

 WriteOnly Property Hour( ) As Integer 

Doing so will cause the compiler to enforce that your property must have a Set and must not have a Get statement. If you leave out the Get or Set without marking the property WriteOnly or ReadOnly , respectively, you will receive a compile error.

You are not permitted to combine ReadOnly with WriteOnly , but this is not much of a burden .

   


Learning Visual Basic. NET
Learning Visual Basic .Net
ISBN: 0596003862
EAN: 2147483647
Year: 2002
Pages: 153
Authors: Jesse Liberty

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