7.3. Surcharge statique et dynamique
(à partir de la doc. Delphi ÔBorland-Inprise )


Plan du chapitre:

1.  Principes généraux de la surcharge d'une méthode en Delphi
 

1.1 Répartition des méthodes en Delphi
1.2 Méthodes statiques en Delphi
1.3 Méthodes virtuelles en Delphi
1.4 Méthodes dynamiques en Delphi
 
2.  Différentes façon de surcharger une méthode en Delphi
 
2.1 Un exemple de surcharge de méthode
2.2 Réutilisation de méthodes statiques avec inherited
2.3 Réutilisation de méthodes dynamiques avec inherited
2.4 Redéfinition de procédures et de fonctions
2.5 Redéfinition de méthodes
2.6 Méthodes abstraites
 


 

1.  Principes généraux de la surcharge d'une méthode en Delphi
 

implementation

{$R *.DFM}

//////// LE  CONSTRUCTOR //////////////////////////////////
constructor MaClasse.create(x:Tcomponent);
begin
 inherited ; // on peut omettre le nom, car la déclaration est identique
{ inherited : pour montrer que bien que caché, on peut atteindre malgré tout le constructor create de la classe parent des Tedit, le override n'est utile que parce que le constructor a été déclaré dans la classe parent du Tedit avec le mot clef technique virtual qui implante une technique équivalente à celle des méthodes virtuelles du langage C++.
}

color:=clyellow;
width:=200;
end;

///// Méthodes de la classe MaClasse ///////////////////////
procedure MaClasse.Un;
begin

text:='MaClasse.Un';
end;

procedure MaClasse.Deux;
begin

text:='MaClasse.Deux';
end;

/// Méthodes de la classe SousClasse /////////////////////////
procedure SousClasse.Un;
begin

inherited ; // on peut omettre le nom, car la déclaration est identique
text:=text+'/SousClasse.Un';
end;

procedure SousClasse.Deux(x:string;c:char);
begin

inherited Deux; // le nom est obligatoire, car les paramètres ne sont pas identiques
text:=text+'/SousClasse.Deux/'+x+'/'+c;
end;

end.
 
 

2.3 Réutilisation de méthodes dynamiques avec inherited

Lors de la surcharge dune méthode dynamique (dynamic ou virtual) le qualificateur inherited est utilisé dune manière identique à celle du paragraphe précédent :

Toutefois en Delphi 3, il est obligatoire que len-tête de la méthode qui " surcharge " soit identique à len-tête de la méthode qui est surchargée (à partir de la version 4 les directives overload et reintroduice permettent de lever cette obligation, cf. § ci-dessous) :
 
MaClasse=class ( Tedit )
  public
Etat:string;
procedure Un;
procedure Deux ; virtual ; // méthode surchargeable
constructor create(x:Tcomponent);
end;
SousClasse=class ( MaClasse )
  public
procedure Un ;
procedure Deux ; override ; // surcharge de la méthode ancêtre (en-tête identique)
end;

implementation

{$R *.DFM}

/// Méthodes de la classe MaClasse ///////////////////////
procedure MaClasse.Deux ;
begin

text:='MaClasse.Deux';
end;

/// Méthodes de la classe SousClasse /////////////////////////
procedure SousClasse.Deux ;
begin

inherited ; // le nom n est pas obligatoire
text:=text+'/SousClasse.Deux/'+x+'/'+c;
end;
 
 

2.4 Redéfinition de procédures et de fonctions

A partir de la version 4, il devient possible de redéclarer plusieurs fois une routine dans la même portée sous le même nom. C'est ce que l'on appelle la redéfinition (ou véritable surcharge indépendante de la signature).
 
Les routines redéfinies doivent être redéclarées avec la directive overload et doivent obligatoirement utiliser une liste de paramètres différente (signature différente).

Soit, par exemple, les déclarations :

function Calcul(X, Y: Real): Real; overload;
begin

Result := X + Y;
end;

function Calcul(X, Y: Integer): Integer; overload;
begin

Result := X * Y;
end;

Ces déclarations créent deux fonctions appelées toutes les deux Calcul qui attendent des paramètres de types différents.

Lorsque vous appelez Calcul, le compilateur détermine la fonction à utiliser en examinant les paramètres effectivement transmis dans l'appel. Ainsi, Calcul(4.57, -12.89) appelle la première fonction Calcul car ses arguments sont des valeurs réelles.
 
 
Les routines redéfinies doivent pouvoir se distinguer par le nombre ou le type de leurs paramètres.

les déclarations suivantes sont correctes :
 
function F1(X: string; Y: real): Real; overload;
...
function F1(X: real; Y: boolean): Real; overload;
...

ou bien
 
function F1(Y: real): Real; overload;
...
function F1(X: real; Y: boolean): char; overload;
...

 
 

2.5 Redéfinition de méthodes
 
  • Une méthode peut être redéclarée en utilisant la directive overload

  •  
  • Dans ce cas, si la méthode redéclarée a une signature de paramètres différente de celle de son ancêtre, elle redéfinit la méthode héritée sans la cacher

  •  
  • L'appel de la méthode dans une classe dérivée active l'implémentation qui correspond aux paramètres utilisés dans l'appel.

 

Si vous redéfinissez une méthode virtuelle, utilisez la directive reintroduce quand vous la redéclarez dans les classes dérivées. Par exemple :
 
 
type
Classe1 = class(TObject)
procedure Exemple(I: real); overload;virtual;
end;
Classe2 = class(Classe1)
procedure Exemple(x,y:integer); reintroduce; overload;
end;

...
UnObjet := Classe2.Create;
UnObjet.Exemple(12.456); // appelle Classe2.Exemple
UnObjet.Exemple(-3,84); // appelle Classe1.Exemple
 

L'implémentation d'une méthode surchargée doit répéter la liste des paramètres spécifiée dans la liste de paramètres de la déclaration de classe :

procedure Classe1.Exemple(I: real);
begin
 ...
end;

procedure Classe2.Exemple(x,y:integer);
begin
 ...
end;
 
 

2.6 Méthodes abstraites

Une méthode abstraite est une méthode virtual ou dynamic dont l'implémentation n'est pas définie dans la déclaration de la classe où elle apparaît ; Son implémentation est déléguée à une classe dérivée. Les méthodes abstraites doivent être déclarées en spécifiant la directive abstract après virtual ou dynamic.
 
 
  • En fait, une méthode abstraite définit une interface sans définir d'action et ne doit doc pas être implémentée. 

  •  
  • Elle joue le rôle d'un prototype d'interface pour les méthodes qui la surchargeront.

Une méthode est abstraite à partir du moment où une directive abstract est insérée dans sa déclaration. Une méthode ne peut être déclarée abstract que si elle est déclarée virtual ou dynamic.
 
procedure AbstraiTruc; virtual; abstract;

function AbstraiChose(x:char):Tobject;dynamic;abstract;

La surcharge d'une méthode abstraite ressemble à celle d'une méthode virtuelle ou dynamique ordinaire, avec toutefois une légère différence dans l'implémentation de la méthode de surcharge :

 
il n'est pas possible de faire appel à une méthode abstraite inherited.

Vous ne pouvez appeler une méthode abstraite que dans une classe ou une instance de classe dans laquelle la méthode a été surchargée.


 

Exemple :
 
type
 Nombre=class
    Valeur_i:integer;
    Valeur_r:real;
    procedure afficher; virtual; abstract;
    procedure add(x:Nombre); virtual; abstract;
  end;

  reel=class(Nombre)
   procedure afficher;override;
   procedure add(x:Nombre);override;
  end;

  entier=class(Nombre)
   procedure afficher; override;
   procedure add(x:Nombre); override;
  end;

  rationnel=class
   num,denom:entier;
  end;