61
Consider the class definition in Ex am ple 2- 4
.
Example 2-4. A class definition
Public Class Employee Public EmployeeNumber As Integer
Public FamilyName As String Public GivenName As String
Public DateOfBirth As Date Public Salary As Decimal
Public Function Format As String Return GivenName FamilyName
End Function End Class
The code in Ex am ple 2- 4
defines a class called Employee. It has five public fields also known as data members for storing state, as well as one member function. The class could be used as shown
in Ex am ple 2- 5
.
Example 2-5. Using a class
Dim emp As New Employee emp.EmployeeNumber = 10
emp.FamilyName = Rodriguez emp.GivenName = Celia
emp.DateOfBirth = 1281965 emp.Salary = 115000
Console.WriteLineEmployee Name: emp.Format Console.WriteLineEmployee Number: emp.EmployeeNumber
Console.WriteLineDate of Birth: emp.DateOfBirth.ToStringD, Nothing
Console.WriteLineSalary: emp.Salary.ToStringC, Nothing
The resulting output is: Employee Name: Celia Rodriguez
Employee Number: 10 Date of Birth: Thursday, January 28, 1965
Salary: 115,000.00
2.14.1 Object Instantiation and New
Object instantiation is done using the New
keyword. The New
keyword is, in effect, a unary operator that takes a type identifier as its operand. The result of the operation is a reference to a newly created
object of the given type. Consider the following: Imports System.Collections
... Dim ht As Hashtable
ht = New Hashtable
The Dim
statement declares a variable that is capable of holding a reference to an object of type Hashtable, but it doesnt actually create the object. The code in the line following the
Dim statement
instantiates an object of type Hashtable and assigns to the variable a reference to the newly created
62
object. As with any other variable declaration, the assignment can be done on the same line as the declaration, as shown here:
Imports System.Collections ...
Dim ht As Hashtable = New Hashtable
Visual Basic .NET permits a typing shortcut that produces the same result: Imports System.Collections
... Dim ht As New Hashtable
2.14.2 Constructors
When a class is instantiated, some initialization often must be performed before the type can be used. To provide such initialization, a class may define a constructor. A constructor is a special kind of
method. It is automatically run whenever an object of the class is instantiated. Constructor declarations use the same syntax as regular method declarations, except that in place of a method name, the
constructor declaration uses the keyword
New . For example:
Public Class SomeClass Public Sub New
Do any necessary initialization of the object here. End Sub
End Class
To invoke the constructor, a new object must be instantiated: Dim obj As New SomeClass
Note the parentheses following the name of the class. Until you get used to it, this method-style
syntax following a class name may appear odd. However, the empty parentheses indicate that the classs constructor takes no arguments.
Constructors can take arguments, if they are necessary for the initialization of the object: Public Class SomeClass
Dim m_value As Integer Public Sub NewByVal InitialValue As Integer
m_value = InitialValue End Sub
End Class
When objects of this class are instantiated, a value must be provided for the constructors argument: Dim obj As New SomeClass27
Constructors can be overloaded, if desired. For example: Public Class SomeClass
Dim m_value As Integer
63
Public Sub New m_value = Date.Today.Day for example
End Sub Public Sub NewByVal InitialValue As Integer
m_value = InitialValue End Sub
End Class
The constructor that is called depends on the arguments that are provided when the class is instantiated, as shown here:
Dim obj1 As New SomeClass calls parameterless constructor Dim obj2 As New SomeClass100 calls parameterized constructor
Constructors are usually marked Public
. However, there are times when it may be desirable to mark a constructor as
Protected or
Private . Protected access prohibits the class from being instantiated
by any class other than a class derived from this class. Private access prohibits the class from being instantiated by any code other than its own. For example, a particular class design might require that
the class itself be in control of whether and when instances are created. Ex am ple 2- 6
shows a class that implements a crude form of object pooling.
Example 2-6. Using a private constructor
Imports System.Collections ...
Public Class MyPooledClass This shared field keeps track of instances that can be handed out.
Private Shared m_pool As New Stack This shared method hands out instances.
Public Shared Function GetInstance As MyPooledClass If m_pool.Count 0 Then
We have one or more objects in the pool. Remove one from the pool and give it to the caller.
Return CTypem_pool.Pop , MyPooledClass Else
We dont have any objects in the pool. Create a new one. Return New MyPooledClass
End If End Function
This method must be called to signify that the client is finished with the object.
Public Sub ImDone Put the object in the pool.
m_pool.PushMe End Sub
Declaring a private constructor means that the only way to instantiate this class is through the GetInstance method.
Private Sub New End Sub
End Class
The class in Ex am ple 2- 6
would be used like this:
64
Dim obj As MyPooledClass = MyPooledClass.GetInstance ...
obj.ImDone
Sometimes when constructors are overloaded, it makes sense to implement one constructor in terms of another. For example, here is a class that has a constructor that takes a SqlConnection object as a
parameter. However, it also has a parameterless constructor that creates a SqlConnection object and passes it to the classs parameterized constructor. Note the use of the
MyClass keyword to access
members of the type: Imports System.Data.SqlClient
... Public Class SomeClass
Public Sub New MyClass.NewNew SqlConnection
End Sub Public Sub NewByVal cn As SqlConnection
Do something with the connection object. End Sub
End Class
Similarly, MyBase.New
can call a base-class constructor. If this is done, it must be done as the first statement in the derived classs constructor. Note that if no explicit call is made, the compiler creates a
call to the base-class constructors parameterless constructor. Even if the base class exposes a parameterized constructor having the same signature i.e., the same number and types of parameters
as the derived classs constructor, by default the compiler generates code that calls the base classs parameterless constructor.
If a class has shared fields that must be initialized before access, and that initialization cant be performed by initializers in the fields declarations, a shared constructor may be written to initialize the
fields, as shown here:
Public Class SomeClass Public Shared SomeStaticField As Integer
Shared Sub New SomeStaticField = Date.Today.Day
End Sub End Class
The shared constructor is guaranteed to run sometime before any members of the type are referenced. If any shared fields have initializers in their declarations, the initializers are assigned to the fields
before the shared constructor is run.
Shared constructors may not be overloaded, nor may they have access modifiers Public
, Private
, etc.. Neither feature is meaningful in the context of shared constructors.
2.14.3 Fields