Administrators PlausiblyDamp Posted September 14, 2004 Administrators Posted September 14, 2004 (edited) Guide to Object Orientated code in .Net This is a continuation of the series started in here and is preceded by this thread Introduction So far we have looked at creating a class that implements several OO concepts (Methods, properties, data hiding and overloading). In this article we will look at another feature � Constructors. Constructors One of the ideas behind OO code is that as much as possible we try to make code self contained and re-usable, one way to do this is to remove the need for people using our code to know how to initialise the internal data structures or require them to remember to call initialisation routines before using our code. In it�s simplest form a Constructor allows our class to do it�s own initialisation before the object is available to any calling code. The declaration of a constructor differs quite substantially between C# and VB.net. If we wished to perform some initialisation in our BankAccount class we could define a constructor as Public Sub New() _Balance = 0 _AccountNumber = 0 End Sub public BankAccount() { _Balance =0; _AccountNumber =0; } As you can see in VB we simply declare a Subroutine called New, while C# uses the C++ style of constructor declaration which uses a method named the same as the class name. Notice that if we want to be able to create an instance of our class the constructors need to be publicly accessible. If we do not declare any constructor then the compile assumes we wanted one that does nothing and would act as if we had declared a constructor like Public Sub New() End Sub public BankAccount() { } If you add the code above to the BankAccount class from the previous article and step through in the debugger you will notice the constructor is automatically called when we create a new instance � there is no way to call it directly. You may also notice that currently it doesn�t really do anything worthwhile as we can already initialise the variables at the point of declaration anyway. However there is one or two other things we can do with constructors to make them more useful. Parameters Just like normal methods constructors can also be passed parameters at run time. A better example than our simplistic one from above could be: Public Sub New(ByVal accountNumber As Integer) _AccountNumber = accountNumber End Sub public BankAccount(int accountNumber) { _AccountNumber =accountNumber; } Allowing us to pass in a valid account number, note if you remove the previous constructor and use the one just above and attempt a recompile it will now fail! The reason being to create an instance we are now required to provide an account number. The auto generated constructor I mentioned above is only generated if we provide no constructors at all, if we provide a constructor that accepts parameters and still require a constructor that doesn�t we need to provide both. To use the new constructor we need to change the way we create an instance of the class like so: Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load AccA = New BankAccount(1) AccB = New BankAccount(2) End Sub private void Form1_Load(object sender, System.EventArgs e) { AccA = new BankAccount(1); AccB = new BankAccount(2); } This now forces users of our class to provide an account number at the point of creation for the object. Overloads Like other class methods constructors can also be overloaded, for example we could chose to specify both an account number and an initial balance when we create a valid instance. Just like normal overloaded methods constructors can delegate part of the work to other versions, however yet again the syntax differs between VB and C# Public Sub New(ByVal accountNumber As Integer, ByVal initialBalance As Decimal) Me.New(accountNumber) _Balance = initialBalance End Sub public BankAccount(int accountNumber) { _AccountNumber = accountNumber; } public BankAccount(int accountNumber, decimal initialBalance) : this(accountNumber) { _Balance = initialBalance; } Note how in C# we simply add : this(accountNumber) to the end of the new constructor while in VB we call the New method directly. When we now create an instance of the BankAccount class we could use either the code provided above or alternatively provide a starting balance like: AccA = New BankAccount(1, 1000) AccB = New BankAccount(2, 500) AccA = new BankAccount(1,1000m); AccB = new BankAccount(2,500m); Again you may find it worthwhile to step through the code in the debugger to get a feel for how the constructors are called in sequence. ReadOnly variables As we have seen previously we can prevent external modification of internal values by exposing read only properties such as Balance, now we have provided a value for _AccountNumber we may want to expose this value to other code in the same way. Public ReadOnly Property AccountNumber() As Integer Get Return _AccountNumber End Get End Property public int AccountNumber { get { return _AccountNumber; } } This style has served us well so far � we provide read only access to the balance and all modifications must go through our provided Credit and Debit methods, however the AccountNumber has an additional feature � namely we do not want the account number to change at all once the class has be instantiated. Not only should it be treated as read only to external code but it should never be modified by other methods in the class either. This can be achieved under .Net by marking the variable as readonly when we define it Private ReadOnly _AccountNumber As Integer private readonly int _AccountNumber =0; this now results in a variable that can have a value provided at compile time and can be modified by a constructor, but no other code is allowed to alter the value at runtime; effectively the value we provide to the constructor is treated as read only once the constructor has exited and a valid instance of the class has been generated. Shared / Static Constructors Another thing to be aware of is that if our class contains shared (static in C#) data members that need initialising we can also provide a static constructor. Shared Sub New() �initialise shared data here End Sub public static BankAccount() { //initialise static data here } These cannot be parameterised nor do we have any control over when they are called � the framework will guarantee that they are called before the class is ever referenced but beyond that we have no control over when. Preventing construction A final thing to be aware of is that if you wish to prevent a class from ever being instantiated (e.g. System.Math or System.Windows.Forms.MessageBox) you can achieve this by creating a non-public default constructor and no publicly accessible ones. Private Sub New() End Sub private BankAccount() { } this can be useful if the class has no instance members or is never intended to be created from an external piece of code but by some internal mechanism. Playtime Again find attached a sample project containing working implementations of the above code. I suggest running the app and stepping through in a debugger to see how the constructors get called, you may want to alter the Form_Load and change the number of parameters being passed to see which Constructors get called. As a final exercise you may want to modify (or add) a method other than a constructor and attempt to assign a new value to _AccountBalance to see what the compiler will report. To Come Next will will look at InheritanceBankVB.zipBankCS.zip Edited May 4, 2005 by PlausiblyDamp Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.