Classes vs. Components
VB.NET has another concept that is very
similar to a class the component. In fact, we can pretty much use a component
and a class interchangeably, though there are some differences that we'll
discuss.
A component is really little more than a regular class, but
it is one that supports a graphical designer within the VB.NET IDE. This means
we can use drag-and-drop to provide the code in our component with access to
items from the Server Explorer or from the Toolbox.
To add a component to a project, select the Project | Add
Component menu option, give the component a name, and click Open
in the Add
New Item dialog.
When we add a class to our project we are presented with
the code window. When we add a component
on the other hand, we are presented with a graphical designer surface, much
like what we'd see when adding a Web Form to the project:
If we switch to the code view (by right-clicking in the
designer and choosing View Code), we will see the code that is created for
us automatically:
This isn't a lot more code than we'd see with a regular
class, though there certainly are differences. First off, we see that this
class inherits from System.ComponentModel.Component.
While we'll discuss the concepts of inheritance in Chapters 6 and 7, it is
important to note here that
this Inherits
line is what brings in all the support for the graphical designer we just saw.
There's also a collapsed region of code in a component. This
region contains code generated by the graphical designer. Here's a quick look
at what is included by default:
#Region " Component Designer generated
code "
Public Sub New(Container As System.ComponentModel.IContainer)
MyClass.New()
'Required for Windows.Forms Class Composition Designer support
Container.Add(me)
End Sub
Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Component overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Component Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
#End Region
As it stands, this code does very little beyond creating
a single Container
class object. However, if we switch the view back to the designer, we can
drag-and-drop items onto our component. For instance, in the Toolbox there is a
Components
tab, which has entries for a variety of useful items such as a MessageQueue,
a DirectoryEntry,
and so forth. If we drag-and-drop a Timer
(from the Components
tab of the Toolbox)
onto our component, it will be displayed in the designer:
From here, we can set its properties using the standard Properties
window in the IDE, just like we would for a control on a form. For instance, we
can set its Name
property to theTimer:
If we now return to the code window and look at the
automatically generated code, we'll see that the region now includes code to
declare, create, and initialize the Timer
object:
#Region " Component Designer generated
code "
Public Sub New(Container As System.ComponentModel.IContainer)
MyClass.New()
'Required for Windows.Forms Class Composition Designer support
Container.Add(me)
End Sub
Public Sub New()
MyBase.New()
'This call is required by the Component Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
End Sub
'Component overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Component Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Component Designer
'It can be modified using the Component Designer.
'Do not modify it using the code editor.
Friend WithEvents theTimer As System.Windows.Forms.Timer
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Me.theTimer = New System.Windows.Forms.Timer(Me.components)
End
Sub
#End Region
Normally, we don't really care about the fact that this code
was generated. Rather, what is important is that we now automatically, simply
by dragging and dropping and setting some properties, have access to a Timer
object named theTimer.
This means that we can
write code within our component, just like we might in a class, to use this object:
Public Sub Start()
theTimer.Enabled = True
End
Sub
Public Sub [Stop]()
theTimer.Enabled = False
End
Sub
Private Sub theTimer_Elapsed(ByVal
sender As System.Object, _
ByVal e As System.Timers.ElapsedEventArgs) Handles theTimer.Elapsed
'
do work
End
Sub
Here we can see that, with a simple drag-and-drop operation,
we've gained access to a variable called theTimer
referencing a Timer
object, and we are able to create methods that interact with and use that
object much like we would with a control dropped onto a form.
For the most part, we can use a component interchangeably
with a basic class, but the use of a component incurs some extra overhead that
a basic class does not, since it inherits all the functionality of System.ComponentModel.Component.
Summary
VB.NET offers us a fully object-oriented language with all
the capabilities we would expect. In this chapter, we've explored the basic
concepts around classes and objects, as well as the separation of interface
from implementation and data.
We've seen how to use the Class keyword to create classes, and how those classes
can be instantiated into specific objects each one an instance of the class.
These objects have methods and properties that can be invoked by client code,
and can act on data within the object stored in member or instance variables.
We also explored some more
advanced concepts, including method overloading, shared or static variables and
methods, and the use of delegates. Finally, we wrapped up with a brief
discussion of attributes and how they can be used to affect the interaction of
our class or our methods with the .NET environment.
In Chapter 6, we'll continue our discussion of object syntax
as we explore the concept of inheritance and all the syntax that enables
inheritance within VB.NET. We will also walk through the creation,
implementation, and use of multiple interfaces a powerful concept that allows
our objects to be used in different ways depending on the interface chosen by
the client application.
Then, in Chapter 7, we'll wrap up our discussion of objects
and object-oriented programming by applying all of this syntax. We'll discuss
the key object-oriented concepts of abstraction, encapsulation, polymorphism,
and inheritance and see how they all tie together to provide a powerful way of
designing and implementing applications.