VB.NET not only provides us with new OO features, but it also changes the way we implement some of the features we are used to from VB6. As we go through these features we’ll cover both the new capabilities and also explore the changes to existing features.
Creating Classes
When building classes in previous versions of VB, each class got its own file. While simple, this solution could cause a larger OO project to have many files. VB.NET allows us to put more than one class in a single source file. While we don’t have to take this approach, it can be nice since we can reduce the overall number of files in a project – possibly making it more maintainable.
Additionally, VB.NET provides support
for the concept of .NET namespaces, as we discussed in Chapters 2 and 3. There
are also changes to the syntax used to create Property
methods, and we can overload methods in our classes. We’ll look at all these
features shortly. First though, let’s look at how we add a class to a project.
Adding a class in VB.NET is similar to adding a class in VB6. In order to do this we need to create a new Windows Application project and choose the Project | Add Class menu option to bring up the Add New Item dialog: |
|
This is the common dialog used for adding
any type of item to our project – in this case it defaults to adding a class
module. Regardless of which type of VB source file we choose (form, class, module,
etc.) we’ll end up with a file ending in a .vb
extension.
It is the content
of the file that determines its type, not the file extension. The IDE creates
different starting code within the file based on the type we choose.
We can name the class TheClass
in this dialog and, when we click Open,
a new file will be added to our project, containing very simple code:
Public Class TheClass
End Class
Though a .vb
file can contain multiple classes, modules and other code, the normal behavior
from the IDE is the same as we’ve had in VB since its inception – one class,
module, or form per file. We can manually add other code to the files created
by the IDE with no problems, but when we ask the IDE to create a class for us
it will always do so by adding a new file to the project.
At this point we’re ready to start adding code.
Class Keyword
As shown in this
example, we now have a Class
keyword along with the corresponding End
Class
. This new keyword is needed in order for a single
source file to contain more than one class. Any time we want to create a class
in VB.NET, we simply put all the code for the class within the Class
…End
Class
block. For instance:
Public
Class TheClass
Public Sub DoSomething()
MsgBox(“Hello world”, MsgBoxStyle.Information,
“TheClass”)
End Sub
End
Class
Within a given source file (any .vb
file) we can have many of these Class
...End
Class
blocks, one after another.
Classes and Namespaces
We discussed the concept of a namespace thoroughly in Chapters 2 and 3. Namespaces are central to the .NET environment, as they provide a mechanism by which classes can be organized into logical groupings, making them easier to find and manage.
Namespaces in VB.NET are declared using a block structure. For example:
Namespace
TheNamespace
Public Class TheClass
End Class
End
Namespace
Any classes, structures, or other types
declared within the Namespace
...End
Namespace
block will be addressed using that namespace.
In this example, our class is referenced using the namespace, so declaring a
variable would be done as follows:
Private obj As TheNamespace.TheClass
Because namespaces are created using a block structure, it is possible for a single source file to contain not only many classes, but also many namespaces.
Also, classes within the same namespace can be created in separate files. In other words, within a VB.NET project we can use the same namespace in more than one source file – and all the classes within those namespace blocks will be part of that same namespace.
For instance, if we have one source file with the following code:
Namespace
TheNamespace
Public Class TheClass
End Class
End
Namespace
And we have a separate source file in the project with the following code:
Namespace
TheNamespace
Public Class TheOtherClass
End Class
End
Namespace
Then we’ll have a single namespace – TheNamespace
– with two classes – TheClass
and TheOtherClass
.
It is also important to remember that
VB.NET projects, by default, have a
root namespace that is part of the project’s properties.
By default this root namespace will have the same name as our project. When
we use the Namespace
block structure, we are actually adding to that root namespace. So, in our example,
if the project is named MyProject
,
then we could declare a variable as:
Private obj As MyProject.TheNamespace.TheClass
To change the root namespace, use the
Project | Properties menu option. The root namespace
can be cleared as well, meaning that all Namespace
blocks become the root level for the code they contain.
Creating Methods
Methods
in VB.NET are created just like they are in VB6 – using the
Sub
or Function
keywords. A method created with Sub
does not return a value, while a Function
must return a value as a result.
Sub DoSomething()
End Sub
Function GetValue()
As Integer
End Function
We retain the three scoping keywords we are used to, and have one more:
-
Private
– callable only by code within our class -
Friend
– callable only by code within our project/component -
Public
– callable by code outside our class -
Protected
– new to VB.NET; we’ll discuss this later when we cover inheritance -
Protected Friend
– callable only by code within our project/component and by code in our subclasses; we’ll discuss this later when we cover inheritance
Parameters to methods are now declared
ByVal
by default, rather than ByRef
.
We can still override the default behavior through explicit use of the
ByRef
keyword. We discussed these issues in more detail in Chapter 3.
Creating Properties
In
Chapter 3 we discussed the changes to the way Property
routines are created. In the past we’d create separate routines for
Property
Get
and Property
Let
. Now these are combined into a single structure:
Private mstrName As
String
Public Property Name()
As String
Get
Return
mstrName
End Get
Set
mstrName
= Value
End Set
End Property
Refer to Chapter 3 for further discussion, including details on creating read-only and write-only properties.
Default Property
When creating classes in VB6 we could declare a default method, or property, for our class. This was done using the Tools | Procedure Attributes menu option and by setting the Procedure ID to (default). Not an entirely intuitive process, since we couldn’t look at the code to see what was going on.
VB.NET changes this behavior in a couple
ways. First off, creating a default property is done through the use of a
Default
keyword – making the declaration much more clear and intuitive. However, VB.NET
introduces a new limitation on default properties – to be default, a property
must be a property array.
A
property
array is a property that is indexed – much like an
array. The Item
property on a collection or list object is an example:
strText = MyList.Item(5)
The Item
property doesn’t have a singular value, but rather is an array of properties
accessed via an index.
By requiring default properties to be
a property array, we allow the language to avoid ambiguities
in the use of default properties. This is a key to the elimination of the Set
keyword as we knew it in VB6. Consider the following code:
MyValue
= MyObject
Does this refer to the object MyObject
,
or to its default property? In VB6 this was resolved by forcing us to use the
Set
command when dealing with the object, otherwise the default property was used.
In VB.NET this statement always refers to the object since a default
property would be indexed. To get at a default property we’d have code such
as:
MyValue
= MyObject(5)
This is not ambiguous, since the index
is a clear indicator that we’re referring to the default property rather than
to MyObject
itself.
This change means a property array procedure must accept a parameter. For example:
Private
theData(100) As String
Default
Public Property Data(ByVal Index As Integer) As String
Get
Data = theData(index)
End Get
Set
theData(index) = Value
End Set
End
Property
In the end, this code is much clearer
than its VB6 counterpart, but we lose some of the flexibility we enjoyed with
default properties in the past. For instance, we’d often use default properties
when working with GUI controls, such as the default Text
property:
TextBox1
= “My text”
This is no longer valid in VB.NET, since
the Text
property is not a property array. Instead we must now use the property name
in these cases.
Overloading Methods
One of the more exciting new polymorphic features in VB.NET is the ability to overload a method. Overloading means that we can declare a method of the same name more than once in a class – as long as each declaration has a different parameter list. This can be very powerful.
A different parameter list means different data types in the list. Consider the following method declaration:
Public Sub MyMethod(X
As Integer, Y As Integer)
The parameter list of this method can be viewed as (integer, integer). To overload this method, we must come up with a different parameter list – perhaps (integer, double). The order of the types also matters, so (integer, double) and (double, integer) are different and would work for overloading.
Overloading cannot be done merely by changing the return type of a function. It is the data types of the actual parameters that must differ for overloading to occur.
As an example, suppose we want to provide a search capability – returning a set of data based on some criteria – so we create a routine such as:
Public Function FindData(ByVal
Name As String) As ArrayList
‘ find data and return
result
End Function
In VB6, if we wanted to add a new searching option based on some other criteria, we’d have to add a whole new function with a different name. In VB.NET however, we can simply overload this existing function:
Public Overloads Function
FindData(ByVal Name As String) As ArrayList
‘ find data and return result
End
Function
Public Overloads Function
FindData(ByVal Age As Integer) As ArrayList
‘ find data and return
result
End Function
Notice that both method declarations have
the same method name – something that would be prohibited in VB6. Each has different
parameters, which allows VB.NET to differentiate between them, and each is declared
with the Overloads
keyword.
When overloading a method we can have
different scopes on each implementation – as long as the parameter lists are
different as we discussed earlier. This means we could change our FindData
methods to have different scopes:
Public
Overloads Function FindData(ByVal Name As String) As ArrayList
‘ find data and return result
End Function
Friend
Overloads Function FindData(ByVal Age As Integer) As ArrayList
‘ find data and return result
End Function
With this change, only other code in our
VB.NET project can make use of the FindData
that accepts an Integer
as its parameter.
Comments