:
: Before anything else, thanks Marina, Workgroups and Ralf, for your
: help.
:
: (Note, I wrote this similar response before, but it got lost while
: posting it!)
:
: As per Marina's response, constructors don't need method calls and a
: new objects can be instanciated without having any constructors
: defined. I tried it in the example and indeed the sum is correctly
: calculated.
:
: As per Workgoups, constructors can be overloaded, but that is the same
: for all procedures isn't it? In the attached modified example, two
: methods with the same name use two and three parameters. It works well
: with and without constructors.
:
: What is then the added value of using constructors?
All reference type objects require a constructor in order to be
instatiated with the New keyword. The idea of the constructor is that it
is a method that is called when an object is first created thus allowing
the object's initial state to be set as needed. Not all classes
necessarily need any kind of initialization in which case an empty
constructor will suffice. In fact, if you don't specify any
constructors, an empty public constructor is automatically supplied by
the compiler. According to the SDK:
"If a type contains no instance constructor declarations, a default
constructor is automatically provided. The default constructor
simply invokes the parameterless constructor of the direct base
type. If the direct base type does not have an accessible
parameterless constructor, a compile-time error occurs. The
declared access type for the default constructor is always
Public."
See my response to your 2nd post for more information on this point.
I have found at least two uses for constructors - initializing an object
when it is first instantiated and controlling how objects are created.
The first of these uses is fairly straight forward and the string
builder class, to pick an arbitrary example, illustrates this. If you
use the empty constructor when creating a new instance of the class, the
object starts out with a default capacity and no initial content. If you
supply an integer in the constructor, you specify the initial capacity
and if you supply a string, you set up the initial content (etc.). This
allows the user to create an object with a single call along these
lines:
Dim sb As New StringBuilder("Initial Content", 100)
Which is functionality equivalent to the following:
Dim sb As New StringBuilder
sb.Append("Initial Content")
sb.Capacity = 100
The second use for constructors can be pretty handy but isn't quite as
obvious at first. Consider the following class:
------------------------------------------
Public Class User
Private mID As String
Private mAlias As String
Private Sub New
End Sub
Public Sun New(UserID As String, _
Password As String)
If UserID <> "Ralf" Then
Throw New Exception("User ID not found")
ElseIf Password <> "Pa$$WoRD" Then
Throw New Exception("Password incorrect")
Else
mID = UserID
mAlias = "_AnonCoward"
End If
End Sub
Public Function CreateUser(UserID As String, _
UserAlias As String) As User
If UserID = "Ralf" Then
Throw New Exception("User ID already exists")
End If
Dim Usr As New User
Usr.mID = UserID
Usr.mAlias = UserAlias
Return Usr
End Function
Public Readonly Property UserID As String
Get
Return mID
End Get
End Property
Public Readonly Property Alias As String
Get
Return mAlias
End Get
End Property
End Class
------------------------------------------
Suppose you wanted to create an instance of the User class from another
context. For example:
------------------------------------------
Public Class [class]
Public Shared Sub Main()
Dim User As New User
End Sub
End Class
------------------------------------------
In this case, you'd get a compile error because there isn't an
accessible constructor that takes no parameters (there is one, but it's
private so you can't call it like this).
On the other hand, this would compile and run just fine:
Dim User As New User("Ralf", "Pa$$WoRD")
In this case, the second constructor is used to validate the input
parameters prior to allowing a user object to be created. If an invalid
User ID or password is supplied when the User object is created, it
throws an exception which can be trapped and handled as shown here:
------------------------------------------
Public Class [class]
Public Shared Sub Main(Args() As String)
Try
Dim User As New User(Args(0), Args(1))
Catch E As Exception
Console.WriteLine("Login Error: " & e.message)
End Try
End Sub
End Class
------------------------------------------
There is another interesting way constructors can be used which is not
all that obvious when you first start out. Consider this function:
------------------------------------------
Public Function CreateUser(UserID As String, _
UserAlias As String) As User
If UserID = "Ralf" Then
Throw New Exception("User ID already exists")
End If
Dim Usr As New User
Usr.mID = UserID
Usr.mAlias = UserAlias
Return Usr
End Function
------------------------------------------
Note that in this case an exception is thrown if the UserID is already
used but otherwise it creates a new instance of the User class and
returns it.
This time however, it invokes the private version of the constructor
(Private Sub New). It can do this because while private functions are
not accessible to objects that are not instances of the class itself
(e.g.: the Sub Main() example earlier), they *can* be accessed by other
instances of the same class. Therefore, the line "Dim Usr As New User"
does not generate a compile error. (Note however, you must declare a
private constructor for this to work - if you don't you'll get a compile
error).
What is even more unexected (at least it was to me when I first ran
across it) is that member variables of a given instance of an object are
visible to, and can be directly manipulated by, other instances of the
same class even if they are declared 'Private'. Notice how the function
above is able to directly set the value of the member variables of the
new User object (Usr) without having to use accessor properties of
functions.
<snip>
HTH
Ralf