Recherche
1 connecté

  Actuellement : 3 commentaires Définir des opérateurs pour une class ou un record

Delphi.NET : Surcharge d'opérateurs pour une classe ou un record.

dernière mise à jour le : samedi 22 mai 2004

Retour au sommaire

cliquez ici pour télécharger le projet complet

Comment définir des opérateurs tels que + - * > etc.. pour une classe ou un record ?

Suposons une classe Matériaux

 TMateriaux = class
    Poids:Integer;
    Volume:Integer;
 end;

Comment faire pour que l'on puisse faire MateriauxResult=Materiaux1 + Materiaux2 avec MateriauxResult.Poids prenant la valeur de Materiaux1.Poids + Materiaux2.Poids et pareil pour le volume ?

Et comme un exemple vaut mieux qu'un long discourt ...

 

unit OperatorUnit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, System.ComponentModel, Borland.Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    ButtonAdd1: TButton;
    ButtonMultiply: TButton;
    ButtonAdd2: TButton;
    procedure ButtonAdd1Click(Sender: TObject);
    procedure ButtonMultiplyClick(Sender: TObject);
    procedure ButtonAdd2Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

  TMateriaux =class
  private
    Poids:Integer;
    Volume:Integer;
  public
    procedure SetPoidsVolume(Poids1, Volume1 :Integer);
    // Add correspond à l'opérateur +
    class operator Add(Materiaux1, Materiaux2: TMateriaux):TMateriaux;
    //on peut avoir plusieurs déclarations de add avec des paramètres différents
    class operator Add(Materiaux1: TMateriaux; i:integer):TMateriaux;
    // Multiply correspond à l'opérateur *
    class operator multiply(Materiaux1: TMateriaux; X:integer):TMateriaux;
  end;

var
  Form1: TForm1;

implementation

{$R *.nfm}

class operator TMateriaux.Add(Materiaux1, Materiaux2: TMateriaux):TMateriaux;
begin
  Result:=TMateriaux.Create;
  Result.Poids:=Materiaux1.Poids+Materiaux2.Poids;
  Result.Volume:=Materiaux1.Volume+Materiaux2.Volume;
end;

class operator TMateriaux.Add(Materiaux1: TMateriaux;
  i: integer): TMateriaux;
begin
  Result:=TMateriaux.Create;
  Result.Poids:=Materiaux1.Poids+i;
  Result.Volume:=Materiaux1.Volume+i;
end;

class operator TMateriaux.multiply(Materiaux1: TMateriaux;
  X: integer): TMateriaux;
begin
 Result:=TMateriaux.Create;
 Result.Poids:=Materiaux1.Poids * X;
 Result.Volume:=Materiaux1.Volume * X;
end;

procedure TMateriaux.SetPoidsVolume(Poids1, Volume1: Integer);
begin
 Poids:=Poids1;
 Volume:=Volume1;
end;

procedure TForm1.ButtonAdd1Click(Sender: TObject);
var
  Materiaux1,  Materiaux2, Materiaux3:TMateriaux;
begin
  Materiaux1:=TMateriaux.Create;
  Materiaux2:=TMateriaux.Create;
  Materiaux3:=TMateriaux.Create;
  Materiaux1.SetPoidsVolume(100,100);
  Materiaux2.SetPoidsVolume(50,50);
  Materiaux3:=Materiaux1+Materiaux2;//première forme de add
  ShowMessage(Format('Poids : %d Volume : %d',[Materiaux3.Poids,
                                           Materiaux3.Volume]));
  //pas besoin de faire de free car il y a le Garbage Collector
end;


procedure TForm1.ButtonAdd2Click(Sender: TObject);
var
  Materiaux1, MateriauxResult:TMateriaux;
begin
  Materiaux1:=TMateriaux.Create;
  MateriauxResult:=TMateriaux.Create; 
  Materiaux1.SetPoidsVolume(100,100);
  MateriauxResult:=Materiaux1+10;//seconde forme de add
  ShowMessage(Format('Poids : %d Volume : %d',[MateriauxResult.Poids,
                                        MateriauxResult.Volume]));
  //pas besoin de faire de free car il y a le Garbage Collector
end;

procedure TForm1.ButtonMultiplyClick(Sender: TObject);
var
  Materiaux1, MateriauxResult:TMateriaux;
begin
  Materiaux1:=TMateriaux.Create;
  MateriauxResult:=TMateriaux.Create;
  Materiaux1.SetPoidsVolume(100,100);
  MateriauxResult:=Materiaux1*2; // multiply;
  ShowMessage(Format('Poids : %d Volume : %d',
             [MateriauxResult.Poids, MateriauxResult.Volume]));
  //pas besoin de faire de free car il y a le Garbage Collector
end;
end.

 

Implicit et Explicit

Parmi les opérateurs pouvant être surchargés, deux sont particulièrement intéressants : Implicit et Explicit qui vont nous permettre de décider du code à exécuter dans les cas suivants :

 

Implicit

Materiaux1:=quelquechose;
//QuelqueChose étant par exemple un integer, un string...
Exemple :  
Matériaux1:=10;
Materiaux1:='10';

Explicit

MaString:= String(Matériaux1);
ou
MonInteger:=Integer(Materiaux1);

Ajoutons à notre TMateriaux les class operator Implicit et Explicit suivantes :

  TMateriaux =class
  private
    Poids :Integer;
    Volume:Integer;
  public
     ......
    class operator Implicit(i:Integer) : TMateriaux ;
    class operator Implicit(S:String) : TMateriaux;
    class operator Explicit (Materiaux:TMateriaux) : String;
    class operator Explicit (Materiaux:TMateriaux) : Integer;
  end;

et implémentons les comme suit :

class operator TMateriaux.Explicit(Materiaux: TMateriaux): String;
begin
   Result:=Format('Poids : %d Volume : %d',[Materiaux.Poids,
                                           Materiaux.Volume])
end;

class operator TMateriaux.Explicit(Materiaux: TMateriaux): Integer;
begin
   Result:=Materiaux.Poids;
end;

class operator TMateriaux.Implicit(i: Integer): TMateriaux;
begin
 Result:=TMateriaux.Create;
 Result.Poids:=i;
 Result.Volume:=0;
end;

class operator TMateriaux.Implicit(S: String): TMateriaux;
begin
 Result:=TMateriaux.Create;
 Result.Poids:=StrToInt(S);
 Result.Volume:=0;
end;

Nous avons maintenant le droit de faire :

procedure TForm1.ButtonImplicitClick(Sender: TObject);
Var
   i:integer;
   Materiaux1:TMateriaux;
begin
  Materiaux1:=TMateriaux.Create;
  Materiaux1:=10; //admirez (Implicit "integer")!
  ShowMessage(Format('Implicit "integer" : Poids = %d Volume = %d',
             [Materiaux1.Poids, Materiaux1.Volume]));
  Materiaux1:='55'; //admirez de nouveau ! (Implicit "string")
  ShowMessage(Format('Implicit "string" : Poids = %d Volume = %d',
             [Materiaux1.Poids, Materiaux1.Volume]));
end;

procedure TForm1.ButtonExplicitClick(Sender: TObject);
Var
   Materiaux1:TMateriaux;
   i:Integer;
begin
  Materiaux1:=TMateriaux.Create;
  Materiaux1.SetPoidsVolume(100,100);
  ShowMessage('Explicit "String : "'+ 
     String(Materiaux1)); //Explicit "String"
  i:=Integer(Materiaux1);//Explicit "Integer"
  ShowMessage('Explicit "Integer" : Poids = '+IntToStr(i));
end;

 

ANNEXE : Liste des correspondances opérateurs / symboles :

Opérateur Catégorie Signature de déclaration Mappage de symbole
Implicit Conversion Implicit(a : type): resultType; implicit typecast
Explicit Conversion Explicit(a: type): resultType; explicit typecast
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
BitwiseNot Unaire BitwiseNot(a: type): resultType; not
Trunc Unaire Trunc(a: type): resultType; Trunc
Round Unaire Round(a: type): resultType; Round
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): resultType; >=
LessThan Comparaison LessThan(a: type; b: type): resultType; <
LessThanOrEqual Comparaison LessThanOrEqual(a: type; b: type): resultType; <=
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
ShiftLeft Binaire ShiftLeft(a: type; b: type): resultType; shl
ShiftRight Binaire ShiftRight(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

 

Retour au sommaire