Operator Overloading

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);



Geef feedback:

CAPTCHA image
Vul de bovenstaande code hieronder in
Verzend Commentaar