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.
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.
|
Related Reading Programming Visual Basic .NET |
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()
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
|
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.
|
Related Reading VB.NET Language in a Nutshell |
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)
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
|
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
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.
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
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.