ONDotNet.com    
 Published on ONDotNet.com (http://www.ondotnet.com/)
 See this if you're having trouble printing code examples


Introduction to VB.NET Object-Oriented Features

by Wei-Meng Lee
05/20/2003

It used to be the case that Visual Basic was regarded as a "toy" language. VB was never treated seriously. This is partly due to the fact that VB does not contain certain advanced features, like pointers access and object-oriented programming. Not anymore! With the launch of the Microsoft .NET framework, Microsoft has catapulted the image of VB programmers to the rank of C and C++ programmers. In this article, I will show you the object-oriented (OO) features of VB.NET and how you can now be on par with your fellow C++ and C# programmers.

OO Basics

The first two terms that you must know are class and object. A class is like a template; it defines the innards of an item. A good analogy is "car." When the word "car" is mentioned, you have the impression of a vehicle with wheels, etc., but no specific make of car is mentioned. An object, in turn, is an instance of a class. A "BMW" is a specific make of a car and hence, it can be likened to an object.

Programming Visual Basic .NET

Related Reading

Programming Visual Basic .NET
By Jesse Liberty

In VB.NET, a class in defined by the following syntax:


Public Class Point

End Class

To create an object from a class, you can use the New keyword:


    Dim pt As New Point()

Our First Example

In Listing 1, I have defined a Point class.

Listing 1. Point Class


Public Class Point
    Private ptX, ptY As Integer
    Private Shared count As Integer

    Public Sub New() '  empty constructor
        count += 1
    End Sub

    '  constructor with two parameters
    Public Sub New(ByVal x As Integer, ByVal y As Integer)
        ptX = x
        ptY = y
        count += 1
    End Sub

    Property x() As Integer '   sets the X coordinate
        Get
            Return ptX
        End Get
        Set(ByVal Value As Integer)
            If Value < 500 And Value > -500 Then
                ptX = Value
            End If
        End Set
    End Property

    Property y() As Integer '   sets the Y coordinate
        Get
            Return ptY
        End Get
        Set(ByVal Value As Integer)
            ptY = Value
        End Set
    End Property

    '  calculates the length between 2 points
    Public Function length(ByVal pointOne As Point) As Single
        Return Math.Sqrt(Math.Pow(ptX - pointOne.x, 2) + _
               Math.Pow(ptY - pointOne.y, 2))
    End Function

    ReadOnly Property counter() As Integer ' returns the counter
        Get
            Return count
        End Get
    End Property

End Class

Within the class, I have two private variables: ptX and ptY. These two variables are only visible within the class.


    Private ptX, ptY As Integer

I also have a shared variable: count. This variable would be shared by all instances of the class. That is, all objects of this class would access the same variable.


    Private Shared count As Integer

In my class, I have two constructors:


    Public Sub New() '  empty constructor
        count += 1
    End Sub

    '  constructor with two parameters
    Public Sub New(ByVal x As Integer, ByVal y As Integer) 
        ptX = x
        ptY = y
        count += 1
    End Sub

The use of a constructor is to initialize the values in an object when it is instantiated (created). A constructor is a subroutine prefixed with the keyword New. The first constructor simply increments the count variable. The second constructor sets the value of the two private variables with the value of the input parameter.

There are a couple of ways to instantiate an object:


Dim pt1 As New Point(3, 4)
Dim pt2 As Point = New Point(5, 6)
Dim pt3 As New Point()
Dim pt4 As Point

The first creates a Point object and calls the second constructor shown earlier. It does so by matching the parameter list. The second instantiation statement is similar to the first. The third instantiation statement calls the first constructor shown above, but does not set any values in the object. The fourth simply creates an object of type Point, but does not actually point to an object. To point to an actual object, it needs to do this:


         pt4 = New Point()

Continuing with the class definition, I have also defined two properties, x and y, using the Property Get and Set keywords.


    Property x() As Integer '   sets the X coordinate
        Get
            Return ptX
        End Get
        Set(ByVal Value As Integer)
            If Value < 500 And Value > -500 Then
                ptX = Value
            End If
        End Set
    End Property

The private variables are used to store the values set by the properties, as shown below:


        '---setting the properties
        pt3.x = 7   '   stores the value 7 into private variable ptX
        pt3.y = 9   '   stores the value 9 into private variable ptY
        Dim x as Integer = pt3.x   '  retrieving the value of ptX

Properties also provide a good opportunity to perform checking to ensure that the user does not assign an invalid value to a property.

I also have a method named length, which returns the length between two points.


    Public Function length(ByVal pointOne As Point) As Single 
        Return Math.Sqrt(Math.Pow(ptX - pointOne.x, 2) + _
               Math.Pow(ptY - pointOne.y, 2))
    End Function

You can use the method through:


        MsgBox(pt1.length(pt2))

Note that this method is public; if it is defined to be a private method like the following, then it cannot be called as above.


    Private Function length(ByVal pointOne As Point) As Single 

Lastly, I have an additional property called counter. Notice that this property has the keyword ReadOnly. This keyword indicates that this property can only be read and cannot be assigned a value such as in the following:


    Pt1.counter = 5      ' not allowed!
    Msgbox (Pt1.counter) ' allowed

Inheritance

In the first example, we have seen how a class can be defined and instantiated. In the next example, we will take a look at how classes can be inherited. Listing 2 shows the class definition of a class called Shape.

Listing 2. Shape Class



Public MustInherit Class Shape
    Dim l, b As Single
    Public MustOverride Function Area() As Single
    Public Overridable Function Perimeter() As Single
        Return 2 * (l + b)
    End Function

    Property length()
        Get
            Return l
        End Get
        Set(ByVal Value)
            l = Value
        End Set
    End Property

    Property breadth()
        Get
            Return b
        End Get
        Set(ByVal Value)
            b = Value
        End Set
    End Property
End Class

The Shape class contains two properties -- length and breadth. It also contains two methods -- Area() and Perimeter(). Let's take a more detailed look at the Shape class now.

VB.NET Language in a Nutshell

Related Reading

VB.NET Language in a Nutshell
By Steven Roman, Ron Petrusha, Paul Lomax

First, the Shape class is defined with the MustInherit keyword. The MustInherit keyword indicates that some other classes must inherit the Shape class; directly instantiating a Shape class is not allowed. For example, the following is not allowed:


    Dim someShapes as New Shape

The Area() method definition contains the keyword MustOverride. The MustOverride keyword is used to define an abstract class. That is, the method itself does not contain any implementation; the classes that inherit from it must implement the actual codes.

The Perimeter() method definition contains the keyword Overridable. Although this method contains the actual implementation, any classes inheriting from it have the option to override its implementation.

Listing 3 shows the class Rectangle inheriting from the Shape class (using the Inherits keyword). It implements the Area() method using the Overrides keyword. The keyword MyBase refers to the base class (i.e., Shape).

Listing 3. Rectangle Class


Public Class Rectangle
    Inherits Shape
    Public Overrides Function Area() As Single
        Return MyBase.length * MyBase.breadth
    End Function
End Class

You can use the Rectangle class:


        Dim r As New Rectangle()
        r.length = 4
        r.breadth = 5
        MsgBox(r.Area)
        MsgBox(r.Perimeter)

Listing 4 shows the Square class inheriting from the Rectangle class.

Listing 4. Square Class


Public NotInheritable Class Square
    Inherits Rectangle
End Class

The Square class contains the NotInheritable keyword, which indicates that this class cannot be inherited. For example, the following is not allowed:


Public Class smallSquare
    Inherits Square
End Class

You can use the Square class:


        Dim s As New Square()
        s.length = 4
        s.breadth = 4
        MsgBox(s.Area)
        MsgBox(s.Perimeter)

Listing 5 shows the Circle class. It overrides both the Area() and Perimeter() methods.

Listing 5. Circle Class


Public Class Circle
    Inherits Shape
    Public Overrides Function Area() As Single
        Return Math.PI * Math.Pow(MyBase.length / 2, 2)
    End Function
    Public Overrides Function Perimeter() As Single
        Return 2 * Math.PI * MyBase.length / 2
    End Function
End Class

You can access the Circle class:



        Dim c As New Circle()
        c.length = 6
        MsgBox(c.Area)
        MsgBox(c.Perimeter)

Overloading and Shadowing

Another important concept in object-oriented programming is method overloading. Consider the example in Listing 6.

Listing 6. BaseClass Class


Public Class BaseClass
    Public Sub Init(ByVal num As Integer)
        MsgBox("Number in BaseClass is " & num)
    End Sub

    Public Sub Init(ByVal st As String)
        MsgBox("String in BaseClass is " & st)
    End Sub
End Class

BaseClass contains two methods of the same name, Init. However, these two methods accept different input parameters. One takes an integer, while the other takes a string.

In Listing 7, the class DerivedClass inherits from the BaseClass, and it too contains two methods called Init, both prefixed by the Overloads keyword.

Listing 7. DerivedClass


Public Class DerivedClass
    Inherits BaseClass
    Overloads Sub Init(ByVal num As Integer)   
	' overloads the method with the same parameter list
        MsgBox("Number in DerivedClass is " & num)
    End Sub

    Overloads Sub Init(ByVal ch As Char)       
	' overloads the method
        MsgBox("Character in DerivedClass is " & ch)
    End Sub
End Class

The following examples should make it clear which methods are active:


'---Shadowing and overloading
Dim d As New DerivedClass()

' prints out "String in BaseClass is Hello VB.NET"
d.Init("Hello VB.NET")    

' prints out "Number in DerivedClass is 5"
d.Init(5)                 

' prints out "Character in DerivedClass is A"
d.Init(Chr(65))           

DerivedClass now exposes three methods with the following input parameters:


    Public Sub Init(ByVal num As Integer)   ' from DerivedClass
    Public Sub Init(ByVal ch As Char)       ' from DerivedClass
    Public Sub Init(ByVal st As String)     ' from BaseClass

In Listing 8, I have another class, DerivedClass2, inheriting from BaseClass. This time, I have the method Init() prefixed with the Shadows keyword.

Listing 8. DerivedClass2 Class


Public Class DerivedClass2
    Inherits BaseClass
    Shadows Sub Init(ByVal num As Integer)     
	' hides all the different argument list
        MsgBox("Number in DerivedClass2 is " & num)
    End Sub
End Class

The Shadows keyword will effectively hide all of the other methods in the class, so now there is only one method exposed in the DerivedClass2 class. The following illustrates this:


        Dim d2 As New DerivedClass2()
        d2.Init(5) ' only one method is exposed

Multiple inheritances of classes are not allowed in VB.NET. That is, you cannot have something like this:


Public Class anotherClass
    Inherits BaseClass
    Inherits DerivedClass   ' Not allowed!
End Class

Interfaces

There are times when you do not want to code the implementation within a class. Interfaces provide a powerful mechanism to separate the definitions of objects from actual implementation. Listing 9 shows three interfaces. Note that only the definitions of methods and properties are present, not the implementation codes.

Listing 9. Vehicle Interface


Interface Vehicle
    Sub Start()
    Sub Brake()
    Sub TurnLeft()
    Sub TurnRight()
    Sub Reverse()
    Sub Accelerate()
    Function GetSpeed()
    Property wheels() As Integer
End Interface

Interface Car
    Inherits Vehicle
End Interface

Interface Dimension
    Property length() As Single
    Property breadth() As Single
End Interface

Listing 10 shows the SportsCar class implementing (using the Implements keyword) the Car and Dimension interfaces. A class that implements an interface must provide implementations for that interface.

Listing 10. SportsCar Class


Public Class SportsCar
    Implements Car
    Implements Dimension

    Public Sub start() Implements Car.Start
        '   implementation codes here
    End Sub
    Public Sub Brake() Implements Car.Brake
        '   implementation codes here
    End Sub
    Public Sub turnleft() Implements Car.TurnLeft
        '   implementation codes here
    End Sub
    Public Sub turnright() Implements Car.TurnRight
        '   implementation codes here
    End Sub
    Public Sub reverse() Implements Car.Reverse
        '   implementation codes here
    End Sub
    Public Sub accelerate() Implements Car.Accelerate
        '   implementation codes here
    End Sub
    Public Function getspeed() Implements Car.GetSpeed
        '   implementation codes here
    End Function
    Property wheels() As Integer Implements Car.wheels
        Get
            '   implementation codes here
        End Get
        Set(ByVal Value As Integer)
            '   implementation codes here
        End Set
    End Property
    Property breadth() As Single Implements Dimension.breadth
        Get
            '   implementation codes here
        End Get
        Set(ByVal Value As Single)
            '   implementation codes here
        End Set
    End Property

    Property length() As Single Implements Dimension.length
        Get
            '   implementation codes here
        End Get
        Set(ByVal Value As Single)
            '   implementation codes here
        End Set
    End Property

End Class

Listing 10 also shows that all of the methods and properties defined by the two interfaces are defined by the SportsCar class. Unlike class inheritance, multiple inheritance in interfaces is allowed, like the following:


Interface Truck
    Inherits Car
    Inherits Dimension
End Interface

Namespaces

The .NET framework uses a dot syntax to group class libraries into easily recognized groups. This naming convention is known as a namespace. For example, the System.Xml.Xsl namespace contains classes that perform XSL transformation. Likewise, in your application you may have many classes, each performing different functions. You may run into name collision, where you have one or more classes with the same name. In this case, you can organize your classes using Namespace:


Namespace Graph
    Public Class Point
       ' Members declaration here
    End Class
End Namespace

Namespace Direction
    Public Class Point
       ' Members declaration here
    End Class
End Namespace

To use the classes with namespaces, you should specify the full namespace:


        Dim ptX As New Graph.Point()
        Dim goNorth As New Direction.Point()

Note: you can also reduce the amount of typing by using the Imports statement:


   Imports MyApplication.Graph
   Dim ptX As New Point()
   

I will talk more about namespaces in a future article.

The Set Keyword

In Visual Basic 6.0, object assignment requires the use of the Set keyword. This has created some confusion for developers who sometimes are just not sure whether to use the Set keyword.


' Visual Basic 6.0
Dim cmdButton As CommandButton
Set cmdButton = Command1

In VB.NET, Microsoft has removed this confusion, and the Set keyword is no longer supported (do not confuse this Set with the one in Property).


' Visual Basic .NET
Dim cmdButton As Button
cmdButton = Button1

Summary

I hope you now have a good grounding in OO concepts in VB.NET. The best way to learn OO concepts is through examples and some experimentation. Go ahead, try it out yourself, and you will very soon discover that you have learnt much more than you have expected.

Wei-Meng Lee (Microsoft MVP) http://weimenglee.blogspot.com is a technologist and founder of Developer Learning Solutions http://www.developerlearningsolutions.com, a technology company specializing in hands-on training on the latest Microsoft technologies.


Return to ONDotnet.com

Copyright © 2009 O'Reilly Media, Inc.