Jump to content
Xtreme .Net Talk

Recommended Posts

  • Administrators
Posted

Guide to Object Orientated code in .Net

 

This is a continuation of the series started in here and is preceded by this thread

 

Introduction

In the previous article we looked at how we could use inheritance to simply the creation of a SavingsAccount class, which contains additional functionality over the BankAccount class, with minimal need to duplicate code and no requirement to alter existing code to work with the new class.

The ability to extend a class in this way can be very useful when developing software, however the ability to change how a derived class implements methods defined in the base class can be very powerful. Imagine our fictitious bank wishes to impose a 1% surcharge on all withdrawals made on Savings Accounts, what we would like is to be able to make this change without having to rewrite existing code that uses our BankAccount and SavingsAccount classes.

 

A Solution?

In a more traditional procedural application we would need to implement this logic at any point where we debit an account � this includes the user interface response to button clicks, the Transfer method etc. The problem with this approach is similar to the problem we encountered with the Transfer method � every time a new class with a different Debit requirement is added existing (and hopefully working & tested) code will need to be modified, possibly introducing bugs or breaking existing functionality. Rather than take this approach it would be better if we could allow each class to be responsible for its own debit method.

If we simply try to give the SaviningsAccount class another Debit method

Public Sub Debit(ByVal amount As Decimal)

End Sub

public void Debit(decimal amount)
{

}

we get a compiler warning regarding a conflict with the base class� Debit method and a suggested fix (adding the keyword Shadows in VB or new in C#), if we follow these instructions then the compiler warning will indeed go away.

Public Shadows Sub Debit(ByVal amount As Decimal)

End Sub

public new void Debit(decimal amount)
{

}

However in either case VB will give a compile time error regarding the conversion from String to Decimal. This error is a result of what the keyword Shadows does � it effectively hides any methods of the same name defined in the base class, therefore the compiler no longer sees the two overloaded versions defined in BankAccount. In C# the new keyword behaves slightly differently as it only hides the Debit method with the same signature � not all Debit methods.

The end result is that if we have a variable declared as type BankAccount calling Debit will use the BankAccount version. If the variable is of type SavingsAccount then it uses the version defined by the SavingsAccount class.

However if this code (C# version anyway) is run a new problem comes to light, namely that the Transfer method declares it�s parameters as being BankAccount � when it debits the accountFrom it will use the version defined in BankAccount and not our new implementation. This is a limitation that can easily be overcome; we just need to indicate what our intention is to the compiler.

 

Polymorphism revisited

Most OO languages (.Net included) provide a mechanism to allow a derived class to re-implement a method provided by the base class without needing unnecessary code duplication. Under .Net we need to state when we need this capability - we do this through the Overridable and Overrides keywords in VB or virtual and override keywords in C#.

Firstly we need to modify the BankAccount class to indicate our intention.

Public Overridable Sub Debit(ByVal amount As Decimal)
   _Balance -= amount
End Sub

public virtual void Debit(decimal amount)
{
_Balance -= amount;
}

and then create a new Debit method in the SavingsAccount class to perform the modified Debit. Rather than duplicate code we will just call the base class� method to perform thee �real� update � we will just perform a slight modification in the derived class.

Public Overloads Overrides Sub Debit(ByVal amount As Decimal)
   MyBase.Debit(amount * 1.01D)
End Sub

public override void Debit(decimal amount)
{
base.Debit(amount * 1.01m);
}

Notice how we use the MyBase and base keywords to call the BankAccount�s method; all we do here is add a 1% charge to the amount being withdrawn.

 

Benefits Gained

Notice that as well as removing the compiler warnings this has also cured the error generated by VB, we now get a clean compile. However the biggest benefit we have gained is found by looking at the Transfer method, even though the parameters are both declared as being BankAccount if we transfer funds from a SavingsAccount (B to A in the attached project) the 1% charge is applied. Also of note is the code executed behind the button click events; both Debit buttons call the overloaded method that takes a string parameter. This method is declared in the base class and was not duplicated in the derived class; however its functionality is still available and is automatically used when a string is passed in.

 

The usefulness is a lot more apparent if you can see the code in action, run the attached sample and step through the code for the debit and transfer buttons. Try changing the variable declarations and types for AccA and AccB, try creating a 3rd account class and overriding it�s debit method to debit with a surcharge that is only applied after 3 debits.

BankCS.zip

BankVB.zip

Posting Guidelines FAQ Post Formatting

 

Intellectuals solve problems; geniuses prevent them.

-- Albert Einstein

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...