Delphi Clinic | C++Builder Gate | Training & Consultancy | Delphi Notes Weblog | Dr.Bob's Webshop |
|
Borland Delphi 4 features a number of Object Pascal language enhancements, as usual. In this article, I'll address a very special language enhancement that was originally only found in C++ development environments, namely Method Overloading.
Method Overloading
Delphi 4 classes can have more than one method with the same name, which is also called method overloading.
Overloaded methods are marked by the keyword overload, and must be made distinguishable by different type signatures in their arguments.
In previous versions of Delphi, classes with more than one constructor had to use separate names for each constructor because there was no method overloading, yet.
All windowed controls had a constructor Create and CreateParented, for example.
Now, all constructors are named Create and overloaded, such as the following two example constructors for a TComponent derived class:
constructor Create(AOwner: TComponent); overload; override; constructor Create(AOwner: TComponent; Text: string); overload;
In the above situation, it would not be legal to declare a third constructor that matched the argument types of one of the first two, such as:
constructor Create(AOwner: TComponent; Name: string); overload;
All Delphi 4 class constructors are now called Create and overloaded, although the differently-named constructors are maintained for backward compatibility. If your code needs to be recompiled with a "lower" version of Delphi, then you should continue using the non-overloaded constructors. Otherwise, I would recommend using the new overloaded Create constructors wherever possible.
Function Overloading
Apart from class constructors and methods (pop question: what about overloaded class destructors?), global functions and procedures can also be overloaded.
program Delphi4; uses Dialogs; procedure LowCase(var C: Char); overload; begin if C in ['A'..'Z'] then C := Chr(Ord(C) - Ord('A') + Ord('a')); end; procedure LowCase(var Str: String); overload; var i: Integer; begin for i:=1 to Length(Str) do LowCase(Str[i]); end; var Str: String = 'Function Overloading in Delphi 4'; begin LowCase(Str); ShowMessage(Str) end.In the above program, we used two overloaded procedures called LowCase. One takes a Char parameter, the other one a String parameter, which is how the compiler can distinguish between them. Note that we cannot add a function LowCase to this program with the following signature:
function LowCase(C: Char): Char; overload; begin if C in ['A'..'Z'] then C := Chr(Ord(C) - Ord('A') + Ord('a')); Result := C end;
Although LowCase is now a function and not a procedure, the compiler cannot distinguish between the two of them when we call LowCase with a character variable, ignoring the result:
LowCase(X);
The compiler could never know if we intended to call the function LowCase and just ignore the function result, or indeed the procedure LowCase.
Overloading and forward declarations
When not using method overloading, the parameters can be omitted from the implementation of a routine that is declared using forward declaration:
procedure Answer(var I: Integer); forward; ... procedure Answer; begin i := 42 end;
When using overloaded methods, however, the parameters must be included in the implementation, or it is unclear whether the implementation matches the forward declaration or introduces a new, parameterless version:
procedure Answer(var I: Integer); overload; forward; ... procedure Answer; overload; { new, parameterless Answer } begin ... end; ... procedure Answer(var I: Integer); overload; { This is the first Answer } begin i := 42 end;
Overloading and default parameters
When using both method overloading and default parameters, don't introduce ambiguous method signatures.
These are considered errors by the compiler.
For example, your application can't include two declarations such as the following:
procedure Answer(I: Integer; J: Integer = 0); overload; procedure Answer(Size: Integer); overload;
This is illegal because it is impossible to tell which procedure is meant by a call to:
Answer(42);