4.6 Overriding

only for RuBoard

As an abstract base, Payment is pretty limited in its current state. You can only overload methods in the class; that is, you can add new methods that have the same name as existing methods. However, existing behavior cannot be redefined. Note that different payment types need to implement Authorize , Bill , and Credit in different ways. Credit cards and checks are authorized through outside companies. However, while credit-card billing is handled by one of those same outside companies, billing a check means that Racer Jim gets an email and the checks are taken down to the bank. Finally, gift certificates are handled in-house; the information is all stored in a database, so there is quite a bit of variation here.

4.6.1 Overridable and Overrides

An existing behavior in a base class can be completely redefined by overriding it in the derived class, but only if the writer of the base class has made it permissible to do so. For a method to be overridden, it must be declared by using the Overridable modifier. Naturally, this suggests some foresight on the part of the class designer. If the method is not marked as overridable, one of two things is happening: the person who coded the class does not want the method to be overridden, or he or she was not thinking ahead of the game. In the latter case, there is a loophole of sorts (see "Shadowing" at the end of this chapter) in the language that allows circumvention of this grievous situation. But for now, assume that the person who wrote the base class had a thinking cap on and defined the Payment class as shown in Example 4-7.

Example 4-7. Overridable methods
 Public MustInherit Class Payment       'Other methods a data here  Public Overridable Function Authorize(ByVal amount As Double) As Boolean  'Base implementation   End Function  Public Overridable Function Bill( ) As Boolean  'Base implementation   End Function  Public Overridable Function Credit( ) As Boolean  'Base implementation   End Function     End Class 

The person deriving a new class can specify that the method is overridden using the Overrides modifier, as shown here:

 Public Class CreditCard : Inherits Payment       'Other methods and data here  Public Overrides Function Authorize(ByVal amount As Decimal) _  As Boolean     'Authorize credit card   End Function  Public Overrides Function Bill( ) As Boolean  'Bill credit card   End Function  Public Overrides Function Credit( ) As Boolean  'Refund credit card   End Function     End Class 

When a method is overridden, the original definition in the base class is completely hidden. To extend the behavior, rather than merely override it, MyBase can be used to call the base class implementation, as shown in the following code:

  Public Overrides Function Bill( ) As Boolean  'Do credit card-specific things here   'then call base class method   '(which updates database)   MyBase.Bill( ) End Function 

4.6.2 MustOverride

Alternatively, the person writing the base class may say, "Hey, there really is no generic behavior for any of this!" It is not uncommon for an abstract base class to require that a behavior be present in a derived class but provide no implementation. As far as flexible design goes, defining an abstract base class with no implementation for its members is the way to go.

Think about the Payment class. No implementation could be provided for Authorize , Bill , or Credit . You have just deluded yourself all along. Yes, you've been in a fantasy world. These operations are handled so differently between one payment type and the next , what would a generic implementation do?

A more realistic way to deal with this issue is to force a derived class to implement a behavior. Derived classes like CreditCard or GiftCertificate can be made to expose a key set of operations by using the MustOverride modifier with the base class' public members, as shown in Example 4-8.

Example 4-8. Creating a contract with MustOverride
 Public MustInherit Class Payment       'No End Function required (Definition only, no implementation)       Public MustOverride Function Authorize(ByVal amount As Double) _       As Boolean       Public MustOverride Function Bill( ) As Boolean       Public MustOverride Function Credit( ) As Boolean     End Class 

C++ programmers might recognize this example as a pure virtual function . This type of function is used when a default behavior cannot be adequately described. However, you also create a guarantee or a contract, which is enforced by the compiler. By creating this guarantee or contract, it is assured that every class deriving from Payment will support these three operations. MustOverride methods actually play an important role in polymorphism.

4.6.3 NotOverridable

When a method is marked Overridable , it is considered that way all the way down the inheritance tree. Suppose the Payment class contains a method that is used internally to verify the validity of an account number. Knowing that every payment type needs a different way to validate this number, the creator of the class has made it overridable:

 Public MustInherit Class Payment          Protected Overridable Function IsValidNumber( ) As Boolean         Return False     End Function      End Class 

Although IsValidNumber was initially defined as overridable, at some point, it might be practical to prevent this override by using the NotOverridable modifier:

 Public Class CreditCard : Inherits Payment   Protected NotOverridable Function IsValidNumber( ) As Boolean     'Use LUHN Mod 10 algorith to validate     'card number    End Function End Class 

NotOverridable prohibits further overriding once it has begun. In this case, the base class Payment provides minimal functionality for the IsValidNumber method. It merely returns False . Realizing the simplicity of the provided functionality, the method is marked as Overridable .

The CreditCard class then overrides this behavior to use the Luhn Mod 10 algorithm to validate card numbers . At this point, it is decided that all credit cards that might be derived in the future should use this algorithm. Therefore, NotOverridable is used to prevent further overriding. This way, new credit card classes cannot be derived, which could potentially sidestep this part of the validation process. ( I f you are interested in seeing how this algorithm works, see the Luhn Mod 10 Algorithm sidebar.)

Don't confuse overriding with overloading. Overriding is the process of defining a method that replaces a method definition with the same signature somewhere up the inheritance tree. Overloading is the process of adding new methods with the same name, but with different arguments.

Luhn Mod 10 Algorithm

The Luhn Mod 10 algorithm validates the numbers of most major credit card companies. Given the credit card number 4111111112127777, here's how it works:

  1. Start from right to left and double the even-numbered digits. If the result is 10 or greater, store the result as two digits (i.e., 1 + 0 for 10, 1 + 1 for 11, 1 + 2 for 12, etc.). Add the results together.

  2. Add the odd-numbered digits to the final result of step 1.

  3. If the total from step 2 is divisible by 10, then the card is valid.

     (Right) 7          = +7 7 * 2 = 14 = +1+4 7          = +7 7 * 2 = 14 = +1+4 2          = +2 1 * 2 =  2 = +2 2          = +2 1 * 2 =  2 = +2 1          = +1 1 * 2 =  2 = +2 1          = +1 1 * 2 =  2 = +2 1          = +1 1 * 2 =  2 = +2 1          = +1  4 * 2 =  8 = +8 ---------------- (Left)       50 Mod 10 = 0 (Number is valid) 

The source code for the Luhn function is:

 Private Function Luhn(ByVal cc As String) As Boolean       Dim i As Integer   Dim total As Integer   Dim even As String   Dim len As Integer = cc.Length   Dim digits(len - 1) As Integer       For i = 0 To len - 1       digits(i) = CInt(cc.Substring(i, 1))   Next i       For i = len - 1 To 1 Step -2       total += digits(i)       even = (digits(i - 1) * 2).ToString("00")       total += Convert.ToInt32(even.Substring(0, 1))       total += Convert.ToInt32(even.Substring(1, 1))   Next i       If len Mod 2 <> 0 Then       total += digits(0)   End If       If total Mod 10 = 0 Then       Return True   End If       Return False   End Function 
only for RuBoard


Object-Oriented Programming with Visual Basic. Net
Object-Oriented Programming with Visual Basic .NET
ISBN: 0596001460
EAN: 2147483647
Year: 2001
Pages: 112
Authors: J.P. Hamilton

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net