Surcharge d'opérateurs

La surcharge d'opérateur est un "sucre syntaxique" associant un opérateur à une fonction selon les types de données utilisés par un opérateur.

Elle permet d'utiliser les opérateurs pour des types personnalisés, une surcharge est déclarée avec la syntaxe

operator <operator> ( <leftType> [, rightType ] ) : <resultType> uses <functionName>;

Par exemple pour surcharger l'opérateur '+' entre une chaîne et TMyClass

type
   TMyClass = class
      Field : String;
   end;

function AddMyClassAndString(s : String; mc : TMyClass) : String;
begin
   Result := s + ' ' + mc.ClassName;
end;

operator + (String, TMyClass) : String uses AddMyClassAndString;

var c := new TMyClass;
c.Field := 'world';

PrintLn('hello' + c); // prints "hello TMyClass"

PrintLn(AddMyClassAndString('hello', c)); // same as previous line

Un opérateur peut aussi être déclaré au sein d'une classe.

Les opérateurs pouvant être surchargés sont:

  • les opérateurs de comparaison: =, <>, >, >=, <, <=, ==, !=, ===
  • les opérateurs de calcul: +, -, *, /, mod, div, shl, shr, sar, or, and, xor, in, implies
  • les opérateur spéciaux: <<, >>, ^
  • les conversions implicites: implicit

Notes importantes:

  • l'implementation d'une surcharge est libre, et peut aller à l'encontre de l'intuition de celui qui lit un code (par exemple rien n'interdit de surcharger l'opérateur + pour lui faire effectuer une soustraction).
  • la portée d'une surcharge est globale après sa définition.
  • les surcharges sont opérateurs par opérateur, par exemple <> et != peuvent être surchargés indépendamment.

Il est donc recommandé de n'utiliser la surcharge qu'avec parcimonie, et dans les cas où elle améliore la compréhension et le la lisibilité, et non uniquement pour réduire le nombre de caractères du code.