Operator overloading is a feature of Delphi, introduced in version 7. It's use is restricted to records, unless you are using Delphi .NET (support for classes too). Not until recently I found a practical usage for them.
One application I am working on makes use of custom colours. For example, it displays system messages in a colour of choice. To select the colour a dialog is used, which returns a TColor. To show the actual messages, a webbrowser component is used, which needs an HTML colour code. I decided to replace my conversion function with a custom colour record and make use of Delphi's operator overloading capabilities. Basically, I made a record that is able to convert between a TColor and a string (the HTML version). Let me show you how.
Basic setup
Start with a new type definition, for example:
type
ThpColor = record
Color: TColor;
class operator Equal(ALeftOp, ARightOp: ThpColor): Boolean;
class operator NotEqual(ALeftOp, ARightOp: ThpColor): Boolean;
class operator Implicit(AValue: ThpColor): string;
class operator Implicit(AValue: ThpColor): TColor;
class operator Implicit(AValue: string): ThpColor;
class operator Implicit(AValue: TColor): ThpColor;
end;
I'll explain what each part is for step by step.
The type
The type I chose to work with is a TColor. It's defined first as a property called Color. This will hold the current value.
Equality check
The next two lines define the equal (=) and not equal (<>) operators. Each function has two parameters, one for the left operand (ALeftOp) of the expression, and one for the right (ARightOp). They are implemented in a very straightforward manner, because I use a simple type:
class operator ThpColor.Equal(ALeftOp, ARightOp: ThpColor): Boolean; begin Result := ALeftOp.Color = ARightOp.Color; end; class operator ThpColor.NotEqual(ALeftOp, ARightOp: ThpColor): Boolean; begin Result := ALeftOp.Color <> ARightOp.Color; end;
Assign your type to another type
If you want to be able to assign your type to something else, you will have to use the Implicit operator overload function with your type as the only parameter. The result of the function must be of the type you want to assign it to. The two functions are implemented to return a TColor (simply returning our internal type) or a string (requires some formatting).
class operator ThpColor.Implicit(AValue: ThpColor): TColor;
begin
Result := AValue.Color;
end;
class operator ThpColor.Implicit(AValue: ThpColor): string;
begin
Result := Format('#%s%s%s', [
IntToHex(GetRValue(AValue.Color), 2),
IntToHex(GetGValue(AValue.Color), 2),
IntToHex(GetBValue(AValue.Color), 2)]);
end;
Assign another type to your type
If you want to assign other types to yours, then you will have to use the Implicit operator overload function too. The parameter has to be of the type you want to copy from, and the result has to be of your type. The TColor conversion is a simple assignment, whereas the string conversion requires some parsing.
class operator ThpColor.Implicit(AValue: TColor): ThpColor;
begin
Result.Color := AValue;
end;
class operator ThpColor.Implicit(AValue: string): ThpColor;
var
R, G, B: Byte;
begin
if Pos('#', AValue) = 1 then
Delete(AValue, 1, 1);
R := StrToIntDef('$' + Copy(AValue, 1, 2), 0);
G := StrToIntDef('$' + Copy(AValue, 3, 2), 0);
B := StrToIntDef('$' + Copy(AValue, 5, 2), 0);
Result.Color := RGB(R, G, B);
end;
In the above string conversion, we check if it starts with a hash-tag and remove it when present. This will allow us to accept #RRGGBB as well as RRGGBB formats.
Some tests
To test if the record we just made does what we want it to do, try the following lines of code (I used a console application for testing).
var
hpColor1, hpColor2: ThpColor;
color1: string;
color2: TColor;
begin
hpColor1 := clRed; // assign a TColor to a ThpColor
hpColor2 := '#ff0000'; // assign a string to a ThpColor
if hpColor1 = hpColor2 then // compare two ThpColor
Writeln('Equal');
color1 := hpColor1; // assign a ThpColor to a string
Writeln(color1);
color2 := hpColor2; // assign a ThpColor to a TColor
if color2 <> hpColor1 then
Writeln('NotEqual');
Readln;
end.
You can step through the code to see what functions are called. In this example it is pretty straightforward, but if you are using multiple conversions on a single line it can get messy real quick.
Download the file
Download the unit with the type definition and comments: hpColor-1.00.zip (1Kb)
Additional reading
Operator Overloading (Delphi) from the Embarcadero wiki shows you the available operator overloading functions.