Advanced Concepts
So far we've seen how to work with objects, how to create
classes with methods, properties, and events, and how to use constructors.
We've also discussed how objects are destroyed within the .NET environment and
how we can hook into that process to do any cleanup required by our objects.
Now let's move on to discuss some more complex topics and
variations on what we've discussed so far. First, we'll cover some advanced
variations in terms of the methods we can implement in our classes, including
an exploration of the underlying technology behind events.
From there we'll move on to delegates, the difference
between components and classes, and .NET attributes as they pertain to classes
and methods.
Advanced Methods
So far, the methods we've worked with have been quite
straightforward. They've either been Sub
or Function
routines. We've also discussed Property
routines, which are a
specialized type of method.
Now let's take a look at some advanced concepts that provide
us with a great deal more power and capability as we work with methods.
Overloading Methods
Methods often accept parameter values. Our Person
object's Walk
method, for instance, accepts an Integer
parameter:
Public Sub Walk(ByVal Distance As Integer)
mintTotalDistance += Distance
RaiseEvent Walked(Distance)
End
Sub
Sometimes we may not want to require the parameter. To solve
this issue we can use the Optional
keyword to make the
parameter optional:
Public Sub Walk(Optional ByVal Distance As Integer = 0)
mintTotalDistance
+= Distance
RaiseEvent
Walked(Distance)
End Sub
This doesn't provide us with a lot of flexibility, however,
since the optional parameter or parameters must always be the last ones in the
list. Additionally, all this allows us to do is choose to pass or not to pass
the parameter suppose we want to do something fancier such as allow different
data types, or even entirely different lists of parameters?
Method overloading
provides exactly those capabilities. By
overloading methods, we can create several methods of the same name,
with each one accepting a different set of parameters or
parameters of different data types.
As a simple example, instead of using the Optional
keyword in our Walk
method, we could use overloading. We'll keep our original Walk
method, but we'll also add another Walk
method that accepts a different parameter list. Change the code in our Person
class back to:
Public Sub Walk(ByVal Distance As Integer)
mintTotalDistance
+= Distance
RaiseEvent
Walked(Distance)
End Sub
Then we can create another
method a method with the same name, but with a different parameter list (in
this case no parameters). Add this code to the class, without removing or changing
the
existing Walk method:
Public Sub Walk()
RaiseEvent Walked(0)
End
Sub
At this point we have two
Walk
methods. The only way to tell them apart is by the list of parameters each
accepts the first requiring a single Integer parameter, the second having
no parameter.
There is an Overloads
keyword as well. This keyword is not needed for simple overloading of methods
as described here, but is required when combining overloading and inheritance.
We'll discuss this in Chapter 6.
Now we have the option of calling our Walk
method in a couple different ways. We can call it
with a parameter:
or without a parameter:
We can have any number of Walk
methods in our class
as long as each individual Walk
method has a different method
signature.
Method Signatures
All methods have a
signature, which is defined
by the method name and the data types of its parameters.
Public Function CalculateValue() As Integer
End Sub
In this example, the signature is f().
The letter f is
often used to indicate a method or function. It is appropriate here, because we
don't care about the name of our
function, only its parameter list is important.
If we add a parameter to the method, the signature will
change. For instance, we could change the method to accept a Double:
Public Function CalculateValue(ByVal Value
As Double) As Integer
Then the signature of the method is f(Double).
Notice that, in VB.NET, the return value is not part of the
signature. We can't overload a Function
routine by just having its
return value's data type vary. It is the data types in the parameter list that
must vary to utilize overloading.
Also make note that the name
of the parameter is totally immaterial only the data type is important. This
means that the following methods have identical signatures:
Public Sub DoWork(ByVal X As Integer, ByVal
Y As Integer)
Public Sub DoWork(ByVal Value1 As Integer,
ByVal Value2 As Integer)
In both cases the signature is f(Integer,
Integer).
Not only do the data types of the parameters define the
method signature, but whether the parameters are passed ByVal
or ByRef
is also important. Changing a parameter from ByVal
to ByRef
will change the method signature.
Combining Overloading and Optional Parameters
Overloading is more flexible than using optional parameters,
but
optional parameters have the advantage that they can be used to provide default
values as well as making a parameter optional.
We can combine the two concepts overloading a method and
also having one or more of those methods utilize optional parameters.
Obviously, this sort of thing could get very confusing if overused, since we're
employing two types of method "overloading" at the same time.
The Optional
keyword causes a single method to effectively have two signatures. This means
that a method declared as:
Public Sub DoWork(ByVal X As Integer,
Optional ByVal Y As Integer = 0)
has two signatures at once: f(Integer,
Integer) and f(Integer).
Because of this, when we use overloading along with optional
parameters, our other overloaded methods cannot match either of these
two signatures. However, as long as our other
methods don't match either signature, we can use overloading as we discussed
earlier. For instance, we could implement methods with the following different
signatures:
Public Sub DoWork(ByVal X As Integer, _
Optional ByVal Y As Integer = 0)
and
Public Sub DoWork(ByVal Data As String)
since there are no conflicting method signatures. In fact,
with these two methods, we've really created three signatures:
q
f(Integer,
Integer)
q
f(Integer)
q
f(String)
The IntelliSense built into the VS.NET IDE will show that we
have two overloaded methods one of which has an optional parameter. This is
different from if we'd created three different overloaded methods to match
these three signatures in which case the IntelliSense would list three
variations on the method from which we can choose.
Overloading the Constructor Method
We can combine the concept
of a constructor method with method overloading to allow for different ways of
creating instances of our class. This can be a very powerful combination, as it
allows a great deal of flexibility in object creation.
We've already explored how to use optional parameters in the
constructor. Now let's change our implementation in the Person
class to make use of overloading instead. Change the existing New
method as follows:
Public Sub New(ByVal Name As String, ByVal BirthDate As Date)
mstrName = Name
mdtBirthDate =
BirthDate
Phone("home")
= "555-1234"
Phone("work")
=
"555-5678"
End Sub
With this change, we've returned to requiring the two
parameter values be supplied.
Now add that second implementation as shown:
Public Sub New()
Phone("home") = "555-1234"
Phone("work") = "555-5678"
End
Sub
This second implementation accepts no parameters meaning
that we can now create Person
objects in two different ways
either with no parameters or by passing the name and birth date:
Dim myPerson As New Person()
or:
Dim myPerson As New Person("Fred",
"1/11/60")
This type of capability is very powerful, as it allows us to
define the various ways in which applications can create our objects. In fact,
the VS.NET IDE takes this into account so, when we are typing the code to
create an object, the IntelliSense tool tip will display the overloaded
variations on the method providing a level of automatic documentation for our
class.