http://www.developer.com/net/vb/article.php/1578341/The-Book-of-Visual-Studio-NET----OOP-in-VB-NET-Crash-Course.htm
As mentioned earlier, Visual Basic did not meet the test as a true object-oriented
language that implements true object-oriented programming as defined by
abstraction, encapsulation, polymorphism, and inheritance. Visual Basic .NET
not only supports inheritance, but also supports a variety of inheritance implementations
including interface, forms, and implementation or polymorphism
inheritance. Before you continue any further, let's briefly discuss the four main concepts
of object orientation and the implementation code for each. Each brief discussion
is followed with an example that demonstrates the discussed OOP concept. Abstraction is the easiest of the OOP concepts to understand and is often something
we implement naturally without realizing it. In short, abstraction is the
implementation of code to mimic the actions and characteristics of any realworld
entity. The most commonly-used example for describing abstraction is the abstraction
of a person. Imagine that we want to create an object from a class that represents a
person. A person class will need to describe its characteristics through the implementation
of properties. Actions of the person class are performed by methods. Encapsulation is the programmatic equivalent of a black box. An actual black
box may have a switch and dials. Inside the box would be the mechanisms to
perform the actions provided by the black box. We expose properties and methods through abstraction, but we implement
the actual workings of our component through encapsulation. A few encapsulated
actions might include data access, data validation, calculations, adding data
to an array or collection, or calling other methods or other components.
Exposing our components interface while hiding the component's implementation
code effectively separates interface implementation from our black
box implementation. This separation helps to modularize components to perform
a more specific task while requiring minimal knowledge of how the black
box actually works. One of the more useful applications of encapsulation is in making a complex
component. For example, your program may require interaction with a
third party system, but interaction with this system can only be achieved
through a complex API. Rather than requiring all developers on a project to
spend valuable time figuring out how to correctly use the third party API or
even find ways to misuse it, one developer could study the API then encapsulate
it in a component that exposes a less complex interface. This is a common practice
that saves time and reduces potential bugs. Like abstraction, encapsulation isn't as much a technology as it is a method
of code implementation. In the case of encapsulation, our method of implementation
separates the exposed interface from the actual implementation code. Abstraction is an interface implemented to represent a real-world object; encapsulation
is the implementation of a black box through interface and implementation
separation; and polymorphism is the ability to implement the interface of another
class into multiple classes or to implement multiple interfaces on a single class.
This method of implementation is referred to as interface-based programming.
A vehicle is a good example of polymorphism. A vehicle interface would
only have those properties and methods that all vehicles have, a few of which
might include paint color, number of doors, accelerator, and ignition. These
properties and methods would apply to all types of vehicles including cars,
trucks, and semi-trucks. Polymorphism will not implement code behind the vehicle's properties and
methods. (That's the job of inheritance covered in the next section.) Instead,
polymorphism is the implementation of an interface. If the car, truck, and semitruck
all implement the same vehicle interface, then the client code for all three
classes can be exactly the same. Implementing the vehicle interface only requires the declaration of properties and methods. To create a new interface, use t he Interface keyword in place of the Class keyword. The client implementing the new interface can do so by using the Implements keyword as shown in the example: After using the Implements keyword, you will notice that Intellisense displays the properties and methods of the IVehicle interface. Using the Implements keyword will only give access to the properties and methods of the IVehicle interface; however, you must provide your own code behind the methods and property declarations to match the interface. Inheritance is the ability to apply another class's interface and code to your own
class. Remember, with polymorphism, you got the interface; however, you must
apply your own code. The power of inheritance is the ability to inherit code, saving
developers time. This type of inheritance is called implementation inheritance.
To inherit another class, use the Inherits keyword. Visual inheritance is the ability to inherit another form's look and feel onto
another. Remember, everything in .NET is a class, including forms. If you create
a project that exists in the MyApp namespace, create a form name MyBaseForm.
The following code will inherit the MyBaseForm within our new form: Properties are part of a program's interface and describe the characteristics of a
class. These properties hold information about a class or, when loaded into
memory, an object. Properties, as they exist in classes, are often referred to as
"data." When a reference is made to a class's data, you will know that the reference
is actually directed toward a class's property. To create a property, use t he Property keyword and t hen define the type of
property you are implementing. Properties can be read-only, write-only, or read
and writable. To define the characteristics of properties, use t he keywords
ReadOnly, WriteOnly, or supply no definition at all to implement both read and
write ability. Visual Studio .NET makes properties easier to implement by adding the
basic shell of property code based on the property's scope definition. Unlike
Visual Basic, Visual Basic .NET automatically supplies code for both read and
write functionality: "Get" for read ability method and "Set" for write access to a
property. Create a new class, type the following code, and press ENTER: Visual Studio .NET will automatically fill in the rest of the code that is
required by the FName property: Methods are the actions exposed by a class in the form of either functions or
sub-procedures. Sub-procedures and functions both execute code on behalf of
the calling application, but sub-procedures simply execute code while functions
execute code, then return a value. The .NET Framework provides at least two new changes to how you can use
procedures. In Visual Basic, you could call a procedure without the use of
parameters, including procedures that required no parameters at all. The .NET
Framework requires parenthesis to follow all methods even when parameters are
not required. For example: Another change is the addition of the Return keyword. When returning a
value for a function in Visual Basic, you set the function's name equal to the
value being returned. With Visual Basic .NET, you can se t the keyword Return
equal to a value and the value will be returned with the function. This is very useful
when making code more generic. For instance, you can easily cut and past a
method's code without regard to another method's function name because the
keyword Return is used for setting the method equal to a return value. Examples
of the old versus new method for returning values of a function are: If you look closely at a function's supporting properties you will find that
the Return keyword is used by default. You can set the function name equal to a
given value. The third significant change is in how parameters are passed. Visual Basic
passed a parameter value ByRef by default. The preferred method for passing
parameter values is to explicitly define whether a value is passed by ByRef or
ByVal. Finally, when using the Option keyword, you must define a default value
similar to how C has worked for many years now. We have covered a few of the most common declaration methods including
those that describe the scope of a property or method. Several description
options will extend or restrict scope. Here is a list of the most commonly-used declaration options with brief
descriptions of each: When you drag and drop controls onto a Windows Form, you are using objects.
When you observe your code, you are looking at a class; when that code is
loaded into memory, at runtime, it is considered an object. The importance of
the distinction is simply to describe that a class is a template, while an object is
an instance of that template in memory. Also, many copies of the template can
exist in memory at the same time as objects. Fortunately, we do not have to depend on the component designer to work
with classes; we can build our own classes and components. This is nothing new
for a moderately experienced developer; what is new is how Visual Basic .NET
permits us to instantiate classes. Classic COM relied on the Windows Registry to store its exposed properties,
methods, events, and enumerations; a client application could only access
these exposed interfaces through the Registry. As a result, the way you instantiate
classes when using classic COM components in COM+ is very important.
Visual Basic .NET accepts a number of instantiation methods without performance
impacts, although all variables must first be diminished and then instantiated
before they can be used. The two methods for instantiating classic COM are the CreateObject and
New keywords. CreateObject uses the Windows Registry to obtain the interface
of the class being instantiated. Because CreateObject depends on windows for
access to the register, COM+ can apply a context for use by the COM+ services.
The New keyword in classic COM also depends on Windows for access to the
Windows Registry. The catch is that it doesn't always have to access the Windows
Registry to discover a class's interface if the class resides inside the same component
as the calling class. Because the New keyword has no problem accessing a
class's interface within the same component, a class can be instantiated by passing
COM+ services that would normally add a context or other component service.
While this will not prevent you from loading a class into COM+, to take full advantage
of COM+ services you should use the CreateObject keyword. Having said all that, the CreateObject keyword cannot be used to instantiate
.NET classes, although it can be used to instantiate classes that exist within classic
COM components. Because .NET components don't rely on the Windows
Registry, the New keyword is used when loading all .NET components.
Here are several examples of how you might define and load classes into
memory. First, the variable is diminished as MyClass: Second, you load the class "MyClass" into memory. An instance of a class
loaded into memory is referred to as an object. Notice there is no "Set" keyword
used. Another method is to declare and instanciate an object in a single line: Finally, you can implicitly diminish a variable with a class you are attempting
to load. This is the shortest method and is perfectly acceptable: Binding is something we do when diminishing a variable, though many developers
may not realize the importance of how they bind a class. Early binding, often referred to as strong typing, refers to explicitly declaring
the class used to define a variable. Early binding has several benefits. For example,
when programming, Visual Studio .NET can give access to the class's interface
with Intellisense which greatly reduces potential for typos and promotes
rapid development. Also, when early binding a class, the Visual Basic compiler
can enforce the proper use of a class's interface by providing warnings and
refusing to complete the compile until the error is resolved. But performance
gains are probably the most important reason to bind early: Early binding allows
your program to access your class's interface directly, rather than through the
Windows Registry or at runtime. If the compiler knows ahead of time which
classes you will be using in your application, it can make the appropriate compilation
optimizations. Late binding can be useful when developing against non-existent components
or ones that are being developed. Late binding allows you to continue
compiling your code until the component is available; once the class is available,
you can modify your code to early bind. You might also use late binding when
you truly don't know the object type that will be passed to your function, in
which case it is perfectly acceptable to accept any type of object.
Before late binding can occur, the Option Strict option must be set to off.
Option strict is off by default: To declare a variable as lat e bound, simply diminish t he variable as type The System.Object class is the class from which all other classes are derived.
While it has no specific characteristics that prevent it from acting as any other
class, it is used for late binding. A class defines something that can exist in memory. It defines an object's interface
including properties, methods, events, and enumerations as well as implementation
code. An object is an instance of a class in memory; while a class may
exist only once, multiple instances of that class may reside in memory as objects.
When adding items to a project, you can add a "class" or a "component
class". In essence, these are the same thing with one exception: a component
class implements the IComponent interface, enabling Visual Studio .NET to
drag non-visual controls, such as the timer control, onto a component designer.
Visual Studio .NET provides a designer for building components, which
allows you to drag visual controls onto your class or component, and begin coding.
For example, if you want to program a delay into your class, you can use a
component item with the designer to drag the timer control onto your component.
The implementation of a graphical designer (IE Component Designer)
and container are available to you when you selected "component class" as a
new item. Visual Studio creates your class by adding a line of code that inherits
everything your class needs to be a component, as follows: Then the designer creates a components object using the IContainer interface
so that the designer can allow drag and drop capabilities: Now you'll build an example application that employs abstraction, encapsulation,
polymorphism, and inheritance: 1. Create a new class library project named "PersonProj". 2. Rename the Class1.vb file to "Person.vb".
3. Add a new Windows Application project to the solution named "TestClient". 4. Right- click on t he TestClient project and select Se t as StartUp Project. Now add abstraction: 1. Replace the default class in Person.vb with the following code: 2. Create a form that looks like Figure 7-2, and name it "frmAbstraction.vb."
Use the parameters in Table 7- 4 to build the new Windows Form. Table 7-4: Form Parameters Control Property Value 3. Right- click on t he TestClient project and select Properties. Change the Startup object to "frmAbstraction.vb". 4. Add a r eference to the PersonProj. Right - click on t he TestClient project and select Add Reference. Select the Projects tab and press the "Select" button then press OK. 5. Add the following object declaration to the initialization of frmAbstraction form: 6. Add the following code to the submit buttons click event: 7. Now run the application. You should be able to place any value you wish into the First and Last name
fields, then completely contradict yourself when filling in your full name. The
same should hold true for entering your birth date and age. This example
abstracts a person but does not hide any implementation; each time you press
the Submit butt on, the Total Hours Worked is summed and displayed. The encapsulation example implements the clsPerson class and encapsulated
code, hiding the implementation code for all the properties and methods.
In the abstraction example, the user has to enter both their birthday and
age. As you encapsulate the implementation for the Person object, you will hide
the implementation of their age. Age will be derived from the person's birth
date, thus preventing a user from creating an invalid age and birth date values.
Properties are also encapsulated, allowing the class to derive the full name from
the first and last names that have been entered. 1. Add a new Windows Form item named "frmEncapsulation.vb". 2. Add the controls and parameters listed in Table 7- 5 to the frmEncapsulation.vb form. Table 7-5: Controls for the Form Control Property Value 3. Create a new class in the Person class using the following code: 4. Add the following object declaration to the initialization of frmAbstraction form: 5. Right- click and select Properties then change the StartUp object to "frmEncapsulation". 6. Add the following code to the Submit button: 7. Now run the application and enter the information. You'll notice that your age is calculated for you so that it cannot contradict
what the age should be based on the birth date, and the full name is derived
from the first and last name. This example features an interface called IPerson and a class named Employee
that uses the IPerson interface: 1. First create a new Windows Form with the same controls as used in the
encapsulation example and name it "frmPolymorphism". 2. Add a new Module to the PersonProj project and name it
"MyInterfaces.vb". 3. Apply the following code to the MyInterface.vb module. The code defines 4. Right- click and select Properties, then change the StartUp object to
"frmPolymorphism". 5. Create a new class to the Person.vb module. You will use it to inherit the new interface: 6. Now run this example just as you ran the previous ones.
You will not notice a difference in how the application runs, although the
plumbing has changed quite a bit. With this simple example, it is easy to question the usefulness of polymorphism.
However, if you were to continue building an application that dealt with
several aspects of a person, you might find polymorphism more helpful to use if
you had to deal with Employees, Customers, Managers, and Contractors. This inheritance example inherits the interface and implementation code of the
clsPerson3 class: 1. Add a new Windows Form item named "frmInheritance.vb". Use the same
controls as we used in the encapsulation example. 2. Add the following code to the initialization section of the form: 3. Add the following class to the Person.vb module of the PersonProj project: 4. Right- click and select Properties, then change the StartUp object to
"frmInheritance". 5. Now Run the inheritance example as you did the previous ones.
Notice that the clsEmployee class inherits the functionality of the clsPerson3
class, which in turn implements the IPerson interface. This example demonstrates
both polymorphism and inheritance that have been combined to form a
single solution. In this chapter, you learned that Visual Basic has come a long way from a
reduced featured-set language that promoted RAPID application development
to a full featured language. Now employing full inheritance, Visual Basic promises
to aid in the delivery of enterprise level applications that may previously
have been better delivered in another OOP language. # # #
The Book of Visual Studio .NET - OOP in VB .NET Crash Course
February 3, 2003
The following is the third of three parts of a chapter on Visual Basic .NET from The Book of Visual Studio .NET, ISBN 1-886411-69-7 from No Starch Press written by Robert B. Dunaway. The first part covered some of the differences between VB .NET from the previous version. The second part presented structured exception handling in Visual Basic .NET. This final part presents OOP concepts in VB .NET.A V I S U A L B A S I C . N E T
C R A S H C O U R S EObject-Oriented Programming (OOP)
Abstraction
Encapsulation
Polymorphism
Implements Ivehicle
Inheritance
Public Class MyNewForm
Inherits MyApp.MyBaseForm
End Class
Properties
Public Property FName() As String
Get
Return m_FName
End Get
Set(ByVal Value As String)
m_FName = Value
End Set
End Property
Methods
intResult = DoSomething
intResult = DoSomething()
Public Function DoSomething() as Int32
DoSomething = 10
End Function
Public Function DoSomething() as Int32
Return = 10
End Function
Declaration Options
Object Instantiation
Dim obj As MyClass
Obj = New MyClass
Dim obj2 As MyClass = New MyClass()
Dim obj3 As New MyClass
Early and Late Binding
Option Strict Off
object:
Option Strict Off
Dim obj As Object
'or
Dim obj As System.Object
Components
Inherits System.ComponentModel.Component
Private components As System.ComponentModel.Icontainer
Simple OOP Examples
Adding Abstraction
Public Class clsPerson
Public FName As String
Public LName As String
Public FullName As String
Public BirthDate As Date
Public Age As Integer
Public TotalHours As Integer
Public Sub Work(ByVal intHours As Integer)
TotalHours += intHours
End Sub
End Class
Button Name btnSubmit
Text Submit
Textbox Name txtFName
Textbox Name txtLName
Textbox Name txtFullName
Textbox Name txtBirthDate
Textbox Name txtAge
Textbox Name txtHoursWorked
Label Name lblTotalHoursWorked
' Here we are initializing the Person class. Normally this would be done
' when the class was needed for data access but in this case we are using
' the Person class to maintain our data.
Dim objPerson As New PersonProj.clsPerson()
objPerson.FName = txtFName.Text
objPerson.LName = txtLName.Text
objPerson.FullName = txtFullName.Text
If IsDate(txtBirthDate.Text) Then
objPerson.BirthDate = CDate(txtBirthDate.Text)
End If
If IsNumeric(txtAge.Text) Then
objPerson.Age = CInt(txtAge.Text)
End If
If IsNumeric(txtHoursWorked.Text) Then
objPerson.Work(CInt(txtHoursWorked.Text))
End If
lblTotalHoursWorked.Text = "Total Hours Worked: " _
& objPerson.TotalHours.ToString
Adding Encapsulation
Button Name btnSubmit
Text Submit
Textbox Name txtFName
Textbox Name txtLName
Label Name lblFullNameDisplay
Textbox Name txtBirthDate
Label Name lblAgeDisplay
Textbox Name txtHoursWorked
Label Name lblTotalHoursWorked
Public Class clsPerson2
Private m_FName As String
Private m_LName As String
Private m_BirthDate As Date
Private m_TotalHours As Integer
Public Property FName() As String
Get
Return m_FName
End Get
Set(ByVal Value As String)
m_FName = Value
End Set
End Property
Public Property LName() As String
Get
Return m_LName
End Get
Set(ByVal Value As String)
m_LName = Value
End Set
End Property
Public ReadOnly Property FullName() As String
Get
Return m_FName & " " & m_LName
End Get
End Property
Public Property BirthDate() As Date
Get
Return m_BirthDate
End Get
Set(ByVal Value As Date)
If IsDate(Value) Then
m_BirthDate = Value
End If
End Set
End Property
Public ReadOnly Property Age() As Integer
Get
If DatePart(DateInterval.Year, m_BirthDate) = 1 Then
Exit Property
End If
Return DateDiff(DateInterval.Year, m_BirthDate, Now)
End Get
End Property
'Method for adding hours to m_TotalHours worked.
Public Sub Work(ByVal intHours As Integer)
m_TotalHours += intHours
End Sub
Public ReadOnly Property TotalHoursWorked() As Integer
Get
Return m_TotalHours
End Get
End Property
End Class
' Here we are initializing the Person class. Normally this would be done
' when the class was needed for data access but in this case we are using
' the Person class to maintain our data.
Dim objPerson As New PersonProj.clsPerson2()
objPerson.FName = txtFName.Text
objPerson.LName = txtLName.Text
If IsDate(txtBirthDate.Text) Then
objPerson.BirthDate = CDate(txtBirthDate.Text)
Else
MsgBox("Please provide a valid Birth Date.")
End If
If IsNumeric(txtHoursWorked.Text) Then
objPerson.Work(CInt(txtHoursWorked.Text))
txtHoursWorked.Text = ""
End If
lblFullNameDisplay.Text = objPerson.FullName.ToString
lblAgeDisplay.Text = objPerson.Age.ToString
lblTotalHoursWorked.Text = "Total Hours Worked: " _
& objPerson.TotalHoursWorked.ToString
Adding Polymorphism or Interface-based Inheritance
the interface.
Public Interface IPerson
Property FName() As String
Property LName() As String
ReadOnly Property FullName() As String
Property BirthDate() As Date
ReadOnly Property Age() As Integer
'Method for adding hours to m_TotalHours worked.
Sub Work(ByVal intHours As Integer)
ReadOnly Property TotalHoursWorked() As Integer
End Interface
Public Class clsPerson3
Implements IPerson
Private m_FName As String
Private m_LName As String
Private m_BirthDate As Date
Private m_TotalHours As Integer
Private m_HrRate As Integer
Private m_TotalPay As Double
Public Property FName() As String _
Implements IPerson.FName
Get
Return m_FName
End Get
Set(ByVal Value As String)
m_FName = Value
End Set
End Property
Public Property LName() As String _
Implements IPerson.LName
Get
Return m_LName
End Get
Set(ByVal Value As String)
m_LName = Value
End Set
End Property
Public ReadOnly Property FullName() As String _
Implements IPerson.FullName
Get
Return m_FName & " " & m_LName
End Get
End Property
Public Property BirthDate() As Date _
Implements IPerson.BirthDate
Get
Return m_BirthDate
End Get
Set(ByVal Value As Date)
If IsDate(Value) Then
m_BirthDate = Value
End If
End Set
End Property
Public ReadOnly Property Age() As Integer _
Implements IPerson.Age
Get
If DatePart(DateInterval.Year, _
m_BirthDate) = 1 Then Exit Property
Return DateDiff(DateInterval.Year, _
m_BirthDate, Now)
End Get
End Property
'Method for adding hours to m_TotalHours worked.
Public Sub Work(ByVal intHours As Integer) _
Implements IPerson.Work
m_TotalHours += intHours
End Sub
Public ReadOnly Property TotalHoursWorked() As Integer _
Implements IPerson.TotalHoursWorked
Get
Return m_TotalHours
End Get
End Property
'Additional Properties:
'HrRate
Public WriteOnly Property HrRate()
Set(ByVal Value)
m_HrRate = Value
End Set
End Property
'TotalPay
Public ReadOnly Property TotalPay() As Double
Get
Return m_HrRate * m_TotalHours
End Get
End Property
End Class
Working with Inheritance
' Here we are initializing the Person class. Normally this would be done
' when the class was needed for data access but in this case we are using
' the Person class to maintain our data.
Dim objPerson As New Person.clsEmployee()
Public Class clsEmployee
Inherits clsPerson3
End Class
Summary
This is the final part of a sample chapter from The Book of Visual Studio .NET, ISBN 1-886411-69-7 from No Starch Press