Intro to Object Orientated Programming Part 6 - Overloading methods

PlausiblyDamp

Administrator
Joined
Sep 4, 2002
Location
Lancashire, UK
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
Visual Basic:
Public Sub Debit(ByVal amount As Decimal)

End Sub
C#:
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.
Visual Basic:
Public Shadows Sub Debit(ByVal amount As Decimal)

End Sub
C#:
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.
Visual Basic:
Public Overridable Sub Debit(ByVal amount As Decimal)
    _Balance -= amount
End Sub
C#:
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.
Visual Basic:
Public Overloads Overrides Sub Debit(ByVal amount As Decimal)
    MyBase.Debit(amount * 1.01D)
End Sub
C#:
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.
 

Attachments

  • BankCS.zip
    11.3 KB · Views: 16
  • BankVB.zip
    9.9 KB · Views: 14
Top Bottom