Surcharge d'opérateurs (Delphi)

De RAD Studio
Aller à : navigation, rechercher

Remonter à Classes et objets - Index


Cette rubrique décrit les méthodes des opérateurs de Delphi et comment les surcharger.

A propos de la surcharge des opérateurs

Delphi autorise la surcharge de certaines fonctions, ou "opérateurs", dans les déclarations d'enregistrement. Le nom de la fonction opérateur correspond à une représentation symbolique dans le code source. Par exemple, l'opérateur Add correspond au symbole +.

Le compilateur génère un appel à la surcharge appropriée, en faisant correspondre le contexte (c'est-à-dire le type de retour et le type des paramètres utilisés dans l'appel) à la signature de la fonction opérateur.

Le tableau suivant énumère les opérateurs Delphi pouvant être surchargés :

Opérateur Catégorie Signature de déclaration Mappage de symbole

Implicit

Conversion

Implicit(a : type) : resultType;

transtypage implicite

Explicit

Conversion

Explicit(a: type) : resultType;

transtypage explicite

Negative

Unaire

Negative(a: type) : resultType;

-

Positive

Unaire

Positive(a: type): resultType;

+

Inc

Unaire

Inc(a: type) : resultType;

Inc

Dec

Unaire

Dec(a: type): resultType

Dec

LogicalNot

Unaire

LogicalNot(a: type): resultType;

not

Trunc

Unaire

Trunc(a: type): resultType;

Trunc

Round

Unaire

Round(a: type): resultType;

Round

In

Ensemble

In(a: type; b: type) : Boolean;

in

Equal

Comparaison

Equal(a: type; b: type) : Boolean;

=

NotEqual

Comparaison

NotEqual(a: type; b: type): Boolean;

<>

GreaterThan

Comparaison

GreaterThan(a: type; b: type) Boolean;

>

GreaterThanOrEqual

Comparaison

GreaterThanOrEqual(a: type; b: type): Boolean;

>=

LessThan

Comparaison

LessThan(a: type; b: type): Boolean;

<

LessThanOrEqual

Comparaison

LessThanOrEqual(a: type; b: type): Boolean;

<=

Add

Binaire

Add(a: type; b: type): resultType;

+

Subtract

Binaire

Subtract(a: type; b: type) : resultType;

-

Multiply

Binaire

Multiply(a: type; b: type) : resultType;

*

Divide

Binaire

Divide(a: type; b: type) : resultType;

/

IntDivide

Binaire

IntDivide(a: type; b: type): resultType;

div

Modulus

Binaire

Modulus(a: type; b: type): resultType;

mod

LeftShift

Binaire

LeftShift(a: type; b: type): resultType;

shl

RightShift

Binaire

RightShift(a: type; b: type): resultType;

shr

LogicalAnd

Binaire

LogicalAnd(a: type; b: type): resultType;

and

LogicalOr

Binaire

LogicalOr(a: type; b: type): resultType;

or

LogicalXor

Binaire

LogicalXor(a: type; b: type): resultType;

xor

BitwiseAnd

Binaire

BitwiseAnd(a: type; b: type): resultType;

and

BitwiseOr

Binaire

BitwiseOr(a: type; b: type): resultType;

or

BitwiseXor

Binaire

BitwiseXor(a: type; b: type): resultType;

xor


Aucun opérateur autre que ceux de ce tableau ne peut être défini sur une classe ou un enregistrement.

Les méthodes d'opérateurs surchargés ne peuvent pas être référencées par nom dans le code source. Pour accéder à une méthode d'opérateur spécifique d'une classe ou d'un enregistrement spécifique, reportez-vous à : Exemple de code :OpOverloads_(Delphi). Les identificateurs d'opérateur sont inclus pour les classes et les enregistrements dans le langage, dans la liste des méthodes de la classe ou de l'enregistrement commençant par le mot "operator" (exemple : Méthodes System.AnsiStringBase). Vous pouvez implémenter les opérateurs ci-dessus dans vos propres classes et enregistrements.

Le compilateur utilisera un opérateur pour une classe ou un enregistrement, à condition que :

  • Pour les opérateurs binaires, l'un des paramètres d'entrée doit être le type de la classe.
  • Pour les opérateurs unaires, le paramètre d'entrée ou la valeur de retour doit être le type de la classe.
  • Pour un opérateur logique et un opérateur bit à bit utilisant le même symbole, l'opérateur logique est seulement utilisé quand les opérandes sont booléens. Puisque le type de la classe de cet opérateur de classe n'est pas un booléen, un opérateur logique sera seulement utilisé quand l'autre opérande est un booléen.

Il n'existe aucune hypothèse concernant les propriétés distributives ou commutatives de l'opération. Pour les opérateurs binaires, le premier paramètre est toujours l'opérande gauche et le second paramètre l'opérande droit. En l'absence de parenthèses explicites, l'associativité est supposée être de gauche à droite.

La résolution des méthodes d'opérateur s'effectue par l'union d'opérateurs accessibles des types utilisés dans l'opération (y compris les opérateurs hérités). Pour une opération impliquant deux types différents (A et B), si le type A a une conversion implicite en B et B a une conversion implicite en A, cela entraîne une ambiguïté. Les conversions implicites ne doivent intervenir que lorsque cela est absolument nécessaire, et la réflexivité doit être évitée. Il est préférable de laisser le type B se convertir implicitement lui-même en type A et laisser le type A n'avoir aucune connaissance du type B (ou vice versa).

En règle générale, les opérateurs ne doivent pas modifier leurs opérandes. A la place, ils renvoient une nouvelle valeur, construite en effectuant l'opération sur les paramètres.

Les opérateurs surchargés sont utilisés plus souvent dans les enregistrements (c'est-à-dire les types de valeur).

Remarque : Les assistances de classes et d'enregistrements ne prennent pas en charge la surcharge d'opérateurs.

Déclaration des surcharges d'opérateurs

Les surcharges d'opérateurs sont déclarées dans des classes ou des enregistrements avec la syntaxe suivante :

type
   typeName = record
       class operator conversionOp(a: type): resultType;
       class operator unaryOp(a: type): resultType;
       class operator comparisonOp(a: type; b: type): Boolean;
       class operator binaryOp(a: type; b: type): resultType;
   end;

L'implémentation des opérateurs surchargés doit aussi inclure la syntaxe class operator :

class operator typeName.conversionOp(a: type): resultType;
class operator typeName.unaryOp(a: type): resultType;
class operator typeName.comparisonOp(a: type; b: type): Boolean;
class operator typeName.binaryOp(a: type; b: type): resultType;

Voici quelques exemples d'opérateurs surchargés :

type
   TMyRecord = record
     class operator Add(a, b: TMyRecord): TMyRecord;      // Addition of two operands of type TMyRecord
     class operator Subtract(a, b: TMyRecord): TMyRecord; // Subtraction of type TMyRecord
     class operator Implicit(a: Integer): TMyRecord;      // Implicit conversion of an Integer to type TMyRecord
     class operator Implicit(a: TMyRecord): Integer;      // Implicit conversion of TMyRecordto Integer
     class operator Explicit(a: Double): TMyRecord;       // Explicit conversion of a Double to TMyRecord
   end;

// Example implementation of Add
class operator TMyRecord.Add(a, b: TMyRecord): TMyRecord;
begin
   // ...
end;

var
x, y: TMyRecord;
begin
   x := 12;      // Implicit conversion from an Integer
   y := x + x;   // Calls TMyRecord.Add(a, b: TMyRecord): TMyRecord
   b := b + 100; // Calls TMyRecord.Add(b, TMyRecord.Implicit(100))
end;

Voir aussi

Exemples de code