only for RuBoard |
Look at Payment.Bill (in Example 4-1) for minute. In its current state, it does not take any parameters. Whatever amount was authorized is the amount that will be billed. But the online shopping world is strange . It is possible that when this payment is billed, not all of the items that were originally purchased will be in stock. Should the order be canceled ? Of course not. You should notify the customer, bill for what you have, and ship the order. The problem is that the customer can't be billed for anything that hasn't shipped. And as it stands now, there is no way to bill a partially available order by using the Payment class.
You need an additional billing method that allows an amount to be specified. It is possible to define two or more methods that have the same name , but a different number of parameters. Then the functionality can be implemented for each case. Example 4-5 shows two versions of Bill : one that accepts an amount and one that does not. This process is called overloading.
Imports System Public MustInherit Class Payment 'Other class methods are here Public Function Bill( ) As Boolean 'Bill authorized amount End Function Public Function Bill(ByVal amount As Double) As Boolean If amount > Me.amount Then amount = Me.amount End If 'Bill specified amount here End Function End Class
If a method is overloaded in a derived class, then it needs to be explicitly expressed by using the Overloads keyword:
Public Class CreditCard : Inherits Payment 'Other methods here 'Overloading method defined in Payment requires keyword Public Overloads Function Bill(ByVal amount As Double) As Boolean 'Bill for amount specified End Function End Class
The compiler knows which call is made based on the parameters that are passed, as the following code fragment shows:
Dim visa As New CreditCard("4111111111111111") visa.Bill( ) 'Calls Payment.Bill visa.Bill(3.33) 'Calls CreditCard.Bill
Overloading is based on the name of the method and the arguments it takes. A method cannot be overloaded by return type, so overloading properties is out of the question.
It is not uncommon for a class designer to overload the constructor of a class and provide several different ways to initialize an object. In the .NET class library, for instance, the String class provides several different constructors.
A string can be initialized with a literal:
Dim someString As String = "Literal"
or an array of characters :
Dim otherString As New String(New Char( ) {"a"c, "r"c, "r"c, "a"c, "y"c})
|
The string can be initialized with a character and an integer that represents how many times the character should be repeated:
'A string that contains 10 question marks Dim thatString As String = New String("?"c, 10)
These constructors are just a few that are defined for a string. This was accomplished by overloading the New method to handle the various types of arguments. Notice that no two constructors have the same signature. You can similarly define constructors with different signatures for your own classes to provide more than one way to initialize your object. However, you should know how overloading a constructor differs from overloading an ordinary method.
Constructors are not inherited, so, technically, they cannot be overloaded from one class to the next . The compiler does, however, add a call to the default constructor (a constructor that has no arguments) in the parent class from the derived class, effectively chaining the classes together. This move is sensible because the derived class might rely on the parent class being in a known state. If a default constructor isn't explicitly defined, the compiler puts an empty one into the class during compilation. Example 4-6 demonstrates the process.
Imports System Public MustInherit Class Payment Public Sub New( ) Console.WriteLine("Payment.New") End Sub Public Sub New(ByVal account As String) Console.WriteLine("Payment.New: {0}", acctNumber) End Sub End Class Public Class CreditCard : Inherits Payment Public Sub New( ) Console.WriteLine("CreditCard.New") End Sub Public Sub New(ByVal account As String) Console.WriteLine("CreditCard.New: {0}", account) End Sub End Class Friend Class Test Public Shared Sub Main( ) Dim visa As New CreditCard( ) Dim amex As New CreditCard("3111111111111") End Sub End Class
Both the child class and the parent class define constructors with the same signatures. Regardless of which constructor is called in the subclass, though, the default constructor in the base class is always called first, even if the parameterized constructor is called:
Payment.New CreditCard.New Payment.New CreditCard.New: 3111111111111
Remember that the default constructor is called first, not the New method with the matching signature. In this case, the base class constructor with the matching function signature should be called instead of the default constructor. You can call it by using the MyBase keyword to call the appropriate base class constructor directly from the derived constructor as follows :
Public Class CreditCard : Inherits Payment Public Sub New( ) Console.WriteLine("CreditCard.New") End Sub Public Sub New (ByVal acctNumber As String) MyBase.New(acctNumber) Console.WriteLine("CreditCard.New: {0}", acctNumber) End Sub End Class
Now the following line of code:
Dim amex As New CreditCard("3111111111111")
Would produce this expected result:
Payment.New: 311111111111111 CreditCard.New: 311111111111111
The default constructor of the base class is not called at all.
|
only for RuBoard |