Een operator overload is een manier die definieert hoe een object gemanipuleerd moet worden als er bepaalde operatoren op los gelaten worden. Een nieuw concept voor Delphi gebruikers, want het is voor het eerst aanwezig in Delphi 8 voor .NET.
Een nieuw concept voor Delphi gebruikers
Het is overigens niet zo dat iedere .NET omgeving automatisch ook operator overloading ondersteunt. Operator overloading behoort dan ook niet tot de CLS (Common Language Specification).
Stel, ik heb een simpele klasse, die een Coordinaat voorstelt:
TCoordinaat = class
public
à X,Y : integer;
end;
Ik instantieer twee objecten en tel ze bij elkaar op:
var OptelCoordinaat,
BeginCoordinaat,
EindCoordinaat : TCoordinaat;
begin
OptelCoordinaat := TCoordinaat.Create;
BeginCoordinaat := TCoordinaat.Create;
EindCoordinaat := TCoordinaat.Create;
OptelCoordinaat := BeginCoordinaat + EindCoordinaat;
end;
Als ik dit probeer te compileren, krijg ik de melding: âÂÂOperator not applicable to this operand typeâÂÂ. Uiteraard heeft de compiler geen idee hoe hij twee objecten van het type TCoordinaat bij elkaar op moet tellen. Dit kunnen we echter wel duidelijk maken. Dit is operator overloading.
De code compileert, als ik mijn klasse aanvul:
TCoordinaat = class
public
X,Y : integer;
class operator Add(Coord1, Coord2 : TCoordinaat):
TCoordinaat;
end;
en de implementatie van de methode toevoeg:
class operator TCoordinaat.Add(Coord1,
Coord2: TCoordinaat): TCoordinaat;
begin
Result := TCoordinaat.Create;
Result.X := Coord1.X + Coord2.X;
Result.Y := Coord1.Y + Coord2.Y;
end;
Blijkbaar wordt het + teken gemapt naar de class operator Add. Hetgeen wat aan de ene kant van het + teken staat is Coord1 en de andere kant is Coord2. Het resultaat is uiteraard het Result van de method.
De operator ga ik nog een keer overloaden, want ik wil er ook een getal bij op kunnen tellen.
TCoordinaat = class
public
X,Y : integer;
class operator Add(Coord1, Coord2 : TCoordinaat):
TCoordinaat;
class operator Add(Coord : TCoordinaat;
Aantal : Integer):
TCoordinaat;
end;
class operator TCoordinaat.Add(Coord: TCoordinaat;
Aantal: Integer): TCoordinaat;
Begin
Result := TCoordinaat.Create;
Result.X := Result.X + Aantal;
Result.Y := Result.Y + Aantal;
end;
Nu kan ik ook zoiets doen:
OptelCoordinaat := OptelCoordinaat + 10;
Op deze manier kan je niet alleen het optellen regelen, maar bijna alle operaties:
|
Operator |
Category |
Declaration Signature |
Symbol Mapping |
|
Implicit |
Conversion |
Implicit(a : type) : resultType; |
implicit typecast |
|
Explicit |
Conversion |
Explicit(a: type) : resultType; |
explicit typecast |
|
Negative |
Unary |
Negative(a: type) : resultType; |
- |
|
Positive |
Unary |
Positive(a: type): resultType; |
+ |
|
Inc |
Unary |
Inc(a: type) : resultType; |
Inc |
|
Dec |
Unary |
Dec(a: type): resultType |
Dec |
|
LogicalNot |
Unary |
LogicalNot(a: type): resultType; |
not |
|
BitwiseNot |
Unary |
BitwiseNot(a: type): resultType; |
not |
|
Trunc |
Unary |
Trunc(a: type): resultType; |
Trunc |
|
Round |
Unary |
Round(a: type): resultType; |
Round |
|
Equal |
Comparison |
Equal(a: type; b: type) : Boolean; |
= |
|
NotEqual |
Comparison |
NotEqual(a: type; b: type): Boolean; |
<> |
|
GreaterThan |
Comparison |
GreaterThan(a: type; b: type) Boolean; |
> |
|
GreaterThanOrEqual |
Comparison |
GreaterThanOrEqual(a: type; b: type): resultType; |
>= |
|
LessThan |
Comparison |
LessThan(a: type; b: type): resultType; |
< |
|
LessThanOrEqual |
Comparison |
LessThanOrEqual(a: type; b: type): resultType; |
<= |
|
Add |
Binary |
Add(a: type; b: type): resultType; |
+ |
|
Subtract |
Binary |
Subtract(a: type; b: type) : resultType; |
- |
|
Multiply |
Binary |
Multiply(a: type; b: type) : resultType; |
* |
|
Divide |
Binary |
Divide(a: type; b: type) : resultType; |
/ |
|
IntDivide |
Binary |
IntDivide(a: type; b: type): resultType; |
div |
|
Modulus |
Binary |
Modulus(a: type; b: type): resultType; |
mod |
|
ShiftLeft |
Binary |
ShiftLeft(a: type; b: type): resultType; |
shl |
|
ShiftRight |
Binary |
ShiftRight(a: type; b: type): resultType; |
shr |
|
LogicalAnd |
Binary |
LogicalAnd(a: type; b: type): resultType; |
and |
|
LogicalOr |
Binary |
LogicalOr(a: type; b: type): resultType; |
or |
|
LogicalXor |
Binary |
LogicalXor(a: type; b: type): resultType; |
xor |
|
BitwiseAnd |
Binary |
BitwiseAnd(a: type; b: type): resultType; |
and |
|
BitwiseOr |
Binary |
BitwiseOr(a: type; b: type): resultType; |
or |
|
BitwiseXor |
Binary |
BitwiseXor(a: type; b: type): resultType; |
xor |
(Bron: Borland Delphi 8 helpfile)
Een extra vermelding waard zijn de operators uit de categorie comparison. Hiermee kun je bepalen wanneer een object groter, kleiner, gelijk of juist niet gelijk is dan/aan een ander type.
Met implicit en explicit uit de categorie conversion kun je bepalen hoe je object reageert als het getypecast wordt.
We gaan weer uitbreiden:
TCoordinaat = class
public
X,Y : integer;
class operator Add(Coord1, Coord2 : TCoordinaat):
TCoordinaat;
class operator Add(Coord : TCoordinaat;
Aantal : Integer): TCoordinaat;
class operator Implicit(Coord : Tcoordinaat): Integer;
end;
class operator TCoordinaat.Implicit(Coord: TCoordinaat):
Integer;
begin
Result := Coord.X + Coord.Y;
end;
Dit werkt nu ook:
var OptelCoordinaat : TCoordinaat; Z : integer;
begin
OptelCoordinaat := BeginCoordinaat + EindCoordinaat;
OptelCoordinaat := OptelCoordinaat + 10;
Z := OptelCoordinaat;
end;
Een programmeur die jouw klasse gebruikt (en waarschijnlijk jijzelf ook) verwacht niet dat met deze code een exception kan optreden en ook niet dat er data verloren gaat.
Bij implicit operators dien je er dan ook te zorgen dat dit niet voor kan komen.
Als je dit niet kunt garanderen, gebruik je een explicit operator. De gebruiker van je klasse moet nu een cast gebruiken.
De laatste regel van bovenstaande code wordt dan:
Z := Integer(OptelCoordinaat);