New Object-Oriented Capabilities in VB.NET

VB.NET OO Implementation

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 ClassEnd 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.

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Walking on water and developing software from a specification are easy if both are frozen.” - Edward V Berard