VB.NET-101 Constructors and Methods

G

Guest

Trying to find out what is essential / optional, I made an extremely simple
Class and Module combination to add two numbers. (see below)

It appears that an empty constructor is needed n order to work right,
although I quite don't see what is does in addition to the 2nd constructor.

Also, the example works fine without message calls in either constructor
(the numerical answer is still there and correct!).
I exected it to no longer work and return build or run errors.
Please explain,

Thanks for your help,
John

***************
Public Class CSum

Public mSum As Integer

Public Sub New()
'Sum(0, 0)
End Sub

Public Sub New(ByVal firstNumber As Integer, ByVal lastNumber As Integer)
'Sum(firstNumber, lastNumber)
End Sub

Public Sub Sum(ByVal firstNumber As Integer, ByVal lastNumber As Integer)
mSum = firstNumber + lastNumber
End Sub

End Class

Module Module1

Sub Main()

Dim thisFirstNumber As Integer = 10
Dim thisLastNumber As Integer = 100

Dim thisSum As New CSum

thisSum.Sum(thisFirstNumber, thisLastNumber)

Console.WriteLine("The sum of {0} and {1} = {2}", _
thisFirstNumber, thisLastNumber, thisSum.mSum)

End Sub

End Module
 
M

Marina

An empty one is needed if you don't want to call the one with 2 paramters.
You declared the other constructor, but you are not using. Now that it's
there, if you want to use an empty constructor, you havet o add it (as you
did).

I'm not sure why you expected errors. You called the Sum method. Then you
retrieved the result - makes sense that it shoudl all work to me.
 
G

Guest

I "commented out" the functions calls in both constructors. In all examples
in my book seen so far, where a method with X parameters was used, method
calls with X arguments (unless optional) were placed in each constructor.
Do I now understand that such message calls are not always needed?
When are they needed and when not?

Thanks for your help.
John
 
M

Marina

Sorry, I am not following at all as far as what the parameters in your
methods have to do with your constructors. They are completely separate and
unrelated.

Delete all the constructors in that class you posted as an example. Have
just the Sum method left and variable declaration. Everything should work
fine.

Might be time to get a new book.
 
A

_AnonCoward

:
: Trying to find out what is essential / optional, I made an extremely
: simple Class and Module combination to add two numbers. (see below)
:
: It appears that an empty constructor is needed n order to work right,
: although I quite don't see what is does in addition to the 2nd
: constructor.
:
: Also, the example works fine without message calls in either
: constructor (the numerical answer is still there and correct!).
: I exected it to no longer work and return build or run errors.
: Please explain,
:
: Thanks for your help,
: John
:
: ***************
: Public Class CSum
:
: Public mSum As Integer
:
: Public Sub New()
: 'Sum(0, 0)
: End Sub
:
: Public Sub New(ByVal firstNumber As Integer, _
: ByVal lastNumber As Integer)
: 'Sum(firstNumber, lastNumber)
: End Sub
:
: Public Sub Sum(ByVal firstNumber As Integer, _
: ByVal lastNumber As Integer)
: mSum = firstNumber + lastNumber
: End Sub
:
: End Class
:
: Module Module1
:
: Sub Main()
:
: Dim thisFirstNumber As Integer = 10
: Dim thisLastNumber As Integer = 100
:
: Dim thisSum As New CSum
:
: thisSum.Sum(thisFirstNumber, thisLastNumber)
:
: Console.WriteLine("The sum of {0} and {1} = {2}", _
: thisFirstNumber, thisLastNumber, thisSum.mSum)
:
: End Sub
:
: End Module


I'll be honest and acknowledge up front I'm not entirely sure what you
are asking, so plz forgive me if this doesn't address your qurestion.


The constructors are needed in order to instantiate the class CSum. The
2nd constructor is in fact unneeded in the context you've offered here.


The Sub 'Sum' stands alone - all you need is an instance of the CSum
class and you can call it from there:

'***********************************************
Imports System

Public Class CSum
Public mSum As Integer

Public Sub New()
End Sub

Public Sub Sum(ByVal firstNumber As Integer, _
ByVal lastNumber As Integer)
mSum = firstNumber + lastNumber
End Sub

End Class

Module Module1
Sub Main()
Dim thisFirstNumber As Integer = 10
Dim thisLastNumber As Integer = 100
Dim thisSum As New CSum

thisSum.Sum(thisFirstNumber, thisLastNumber)

Console.WriteLine("The sum of {0} and {1} = {2}", _
thisFirstNumber, thisLastNumber, thisSum.mSum)
End Sub
End Module

'***********************************************


As an alternative, you could have instead declared the CSum class as a
structure. In this case, no contructor is needed at all (in fact, you
get compile errors if you declare an empty structure (uncomment the Sub
New() lines below to see what I mean):


'***********************************************
Public Structure CSum
Public mSum As Integer

' Public Sub New()
' End Sub

Public Sub Sum(ByVal firstNumber As Integer, _
ByVal lastNumber As Integer)
mSum = firstNumber + lastNumber
End Sub

End Structure

'***********************************************


An alternative approach would be to declare Sum as a shared fuction:

'***********************************************
Imports System

Public Class CSum
Public mSum As Integer

Private Sub New()
End Sub

Public Shared Function Sum( _
ByVal firstNumber As Integer, _
ByVal lastNumber As Integer) As Integer
Return firstNumber + lastNumber
End Function

End Class

Module Module1
Sub Main()
Dim thisFirstNumber As Integer = 10
Dim thisLastNumber As Integer = 100
Dim thisSum As Integer

thisSum = CSum.Sum(thisFirstNumber, thisLastNumber)

Console.WriteLine("The sum of {0} and {1} = {2}", _
thisFirstNumber, thisLastNumber, thisSum)
End Sub
End Module

'***********************************************

In this case, you can't create an instance of the CSum class as there
aren't any publicly accessible constructors you can invoke with the New
keyword.



HTH,

Ralf
 
W

Workgroups

Perhaps this is what's tripping you up? Methods can have "multiple
signatures", allowing more than two of the same name:

Sub New ()

We'll call this "Signature #1". And then this...

Sub New (ByVal firstNumber As Integer, ByVal lastNumber As Integer)

We'll call that "Signature #2".

Both of these subroutines called New have the same name, but, they have
different parameter lists (different datatypes in a different order) in
their declarations. This gives each of them a unique "signature", a way
for the compiler and the IDE (and you) to tell the difference between them,
and allows them to exist as completely seperate methods despite having the
same name. Signature #1 has no parmeters, whereas signature #2 has two
integer parameters. These differences are enough to qualify them as unique,
individual methods.

By having 2 "New" constructors in your CSum class, you have provided
yourself with 2 constructors (with different signatures) from which to
choose when creating your class. You can call whichever one you want when
instantiating your class. Class CSum doesn't care which you use. All you
have to do is make your constructor call something that matches one of the
signatures. I.e.,

Dim thisSum As New CSum(10, 100)

That passed two integers to construct a New CSum class object. Since we do
indeed have a constructor that will accept two integers ("New" having
Signature #2), that is the constructor that will be utilized (and Signature
#1 will not be utilized at all, in this case).

Alternatively if you were to say,

Dim thisSum As New CSum

Because no parameters were passed to the constructor, this matches Signature
#1, the parameter-less constructor, and so that is chosen instead of
Signature #2.

The alternative to all of this "multiple signature" business would be to
create a single New constructor with 2 optional integers. It would net you
the same conceptual result. But creating multiple signatures of the same
method is typically a cleaner way of doing it if the amount of parameters is
lengthy, so you don't end up with a method with an optional parameter list a
mile long. Instead, you can make different versions of the same method
(with different signatures) that all eventually call a single base worker
sub, etc.
 
G

gg

pardon me for jumping in.
Please explain when and why would one use shared function without static
variable inside?

I am new to .net and trying to lean. SO please forgive me if I asked a dump
question.
 
A

_AnonCoward

: pardon me for jumping in.
: Please explain when and why would one use shared function without
: static variable inside?
:
: I am new to .net and trying to lean. SO please forgive me if I
: asked a dump question.


According to the documentation that accompanies the SDK:


"The Shared keyword indicates that one or more declared programming
elements are shared. Shared elements are not associated with a specific
instance of a class or structure. You can access them by qualifying them
either with the class or structure name, or with the variable name of a
specific instance of the class or structure."


In short, a Shared (static in C#) function is one that exposes
functionality that is not part of a given instance. Shared functions may
not operate on instance variables. The previous example, while trivial,
is an example:


Public Class CSum
Public Shared Function Sum(ByVal First As Integer, _
ByVal Last As Integer) As Integer
Return First + Last
End Function
End Class


The function simply returns the sum of two integers passed in. You don't
need an instance of the CSum class to access this functionality.


A non-trivial example of a Shared function is the System.Console class.
You cannot create an instance of this class nor do you need to in order
to use the various functions it exposes (e.g.: WriteLine).


HTH

Ralf
 
G

Guest

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?

The 2nd part of my original question (and code) referred to the observation
that the method with only two-argument constructor caused a build error which
disappeared after adding the empty constructor. I do not understand why.

******************************
Public Class CSum

Public mSumOfTwo As Integer
Public mSumOfThree As Integer

'Public Sub New()
'End Sub

'Public Sub New(ByVal first As Integer, ByVal second As Integer)
'Sum(0, 0)
'End Sub

'Public Sub New(ByVal first As Integer, ByVal second As Integer, ByVal
third As Integer)
'Sum(0, 0, 0)
'End Sub

Public Sub Sum(ByVal first As Integer, ByVal second As Integer)
mSumOfTwo = first + second

Console.WriteLine("The sum of {0} and {1} = {2}", _
first, second, mSumOfTwo)
End Sub

Public Sub Sum(ByVal first As Integer, ByVal second As Integer, ByVal
third As Integer)
mSumOfThree = first + second + third

Console.WriteLine("The sum of {0} and {1} and {2} = {3}", _
first, second, third, mSumOfThree)
End Sub

End Class
******************************

Module Module1

Sub Main()

Dim thisFirstNumber As Integer = 10
Dim thisSecondNumber As Integer = 100
Dim thisLastNumber As Integer = 1000

Dim thisSum As New CSum

thisSum.Sum(thisFirstNumber, thisSecondNumber)

thisSum.Sum(thisFirstNumber, thisSecondNumber, thisLastNumber)

End Sub

End Module
*************************************
Again, thanks for your support,

John

*************************************
 
G

Guest

I guess that this tread is no longer followed. I will post it as a new one.
John
************************
 
A

_AnonCoward

:
: 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top