5.5 NOTICE METHODOLOGIQUE
construire un nouvel événement


Code pratique : une pile Lifo événementielle



Objectif : Nous proposons ici en suivant pas à pas l'enrichissement du code de montrer comment implanter un nouvel événement nommé OnTruc dans une classe dénotée ClassA. Puis nous appliquerons cette démarche à une pile Lifo qui sera rendu sensible à l'empilement et au dépilement, par adjonction de deux événements à la classe.

Pour construire un nouvel événement dans ClassA :

 
Version-1 du code source

Unit  UDesignEvent  ;
 
 interface
 type
  
EventTruc  =  procedure  ( Sender: TObject ;  info :string )  of  object  ;
  
  
ClassA  =  class
 private
  
FOnTruc  :  EventTruc  ;
 public
  
OnTruc  :  EventTruc  read  FOnTruc   write  FOnTruc  ;
end;

implementation
 
 
end.


 
Lorsque l'événement se nomme OnXXX, les équipes de développement Borland donnent la fin du nom de l'événement OnXXX à la procédure redéfinissable. Ici  pour l'événement OnTruc à la place de DeclencheTruc, nous la nommerons Truc.

Version-2 du code source

Unit  UDesignEvent  ;
 
 interface
 type
  
EventTruc  =  procedure  ( Sender: TObject ;  info :string )  of  object  ;
  
ClassA  =  class
 private
  
FOnTruc  :  EventTruc  ;
 protected
  procedure 
Truc(s :string ) ; virtual ;  // surchargeable dynamiquement
 
public
  
OnTruc  :  EventTruc  read  FOnTruc   write  FOnTruc  ;
end;

implementation
 
 procedure 
ClassA.Truc(s :string ) ;
 begin
  if 
Assigned ( FOnTruc )  then
   
FOnTruc ( self  , s)
 
end;
 
end.



Nous définissons une classe ClasseUse qui utilise sur un objet de classe ClassA l'événement OnTruc.

 

Version-3 du code source

Unit  UDesignEvent  ;
 
 interface
 type   
EventTruc  =  procedure  ( Sender: TObject ;  info :string )  of  object  ;
  
  
ClassA  =  class
 private
  
FOnTruc  :  EventTruc  ;
 protected
  procedure 
Truc(s :string ) ; virtual ;  // surchargeable dynamiquement
 
public
  
ObjA  :  ClassA  ;
  
OnTruc  :  EventTruc  read  FOnTruc   write  FOnTruc  ;
  procedure 
LancerTruc ;  // Declenche l'événement OnTruc
end;

ClasseUse  =  class
 public
  procedure 
method_100( Sender: TObject ;  info :string ) ;
  procedure 
method_101( Sender: TObject ;  info :string ) ;
  procedure 
method_102( Sender: TObject ;  info :string ) ;
  procedure 
method_103( Sender: TObject ;  info :string ) ;
  procedure 
principale ;
end;

implementation
 
 
{-------------------  ClassA   ------------------------}
 
procedure  ClassA.Truc(s :string ) ;
 begin
  if 
Assigned ( FOnTruc )  then
   
FOnTruc ( self  , s)
 
end;
 
 procedure 
ClassA.LancerTruc  ;
 begin
  
....
  Truc ("événement déclenché")
;
  
....
 
end;
 
{-------------------  ClasseUse   ------------------------}
 
procedure  ClasseUse.principale ;
 begin
  
//....
  
ObjA  :=  ClassA.Create  ;
  
ObjA.OnTruc  :=  method_102  ;  // connexion
  //....
  
ObjA.LancerTruc  ;  // lancement
 
end;
 
 procedure 
ClasseUse.method_100( Sender: TObject ;  info :string ) ;
 begin
  
//....
 
end;
 
 procedure 
ClasseUse.method_101( Sender: TObject ;  info :string ) ;
 begin
  
//....
 
end;
 
 procedure 
ClasseUse.method_102( Sender: TObject ;  info :string ) ;
 begin
  
//....
 
end;
 
 procedure 
ClasseUse.method_103( Sender: TObject ;  info :string ) ;
 begin
  
//....
 
end;
 
end.

 


Code pratique : une pile Lifo événementielle

Objectif : Nous livrons une classe de pile lifo héritant d'une Tlist (Un objet Tlist de Delphi, stocke un tableau de pointeurs, utilisé ici pour gérer une liste d'objets) et qui est réactive à l'empilement et au dépilement d'un objet. Nous suivons la démarche précédente en nous inspirant de son code final pour construire deux événements dans la pile lifo et lui permettre de réagir à ces deux événements.


unit   ULifoEvent  ;
 
 interface
 uses  
classes,Dialogs  ;
  
 type
  
DelegateLifo  =  procedure  (  Sender:  TObject  ;   s  :string  )  of   object  ;
  
  
ClassLifo  =  class  (TList)
 
private
  
FOnEmpiler  :  DelegateLifo  ;
  
FOnDepiler  :  DelegateLifo  ;
 public
  function  
Est_Vide   : boolean  ;
  procedure  
Empiler (elt  : string  )  ;
  procedure  
Depiler (  var   elt  : string  )  ;
   property  
OnEmpiler  :  DelegateLifo   read   FOnEmpiler   write   FOnEmpiler  ;
   property  
OnDepiler  :  DelegateLifo   read   FOnDepiler   write   FOnDepiler  ;
end;

ClassUseLifo  =  class
 public
  procedure  
EmpilerListener(  Sender:  TObject  ;   s  :string  )  ;
  procedure  
DepilerListener(  Sender:  TObject  ;   s  :string  )  ;
  constructor  
Create  ;
  procedure  
main  ;
end;

implementation
 
 procedure  
ClassLifo.Depiler(  var   elt  : string  )  ;
 begin
  if  
not   Est_Vide   then
  begin
   
elt  :=string  (self.First)  ;
   
self.Delete(0)  ;
   
self.Pack  ;
   
self.Capacity  :=  self.Count  ;
   if  
assigned(FOnDepiler)   then
    
FOnDepiler (  self  ,elt )
  
end
 end;
 
 procedure  
ClassLifo.Empiler(elt  : string  )  ;
 begin
  
self.Insert(0 , PChar(elt))  ;
  if  
assigned(FOnEmpiler)   then
   
FOnEmpiler (  self  ,elt )
 
end;
 
 
 function  
ClassLifo.Est_Vide  : boolean  ;
 begin
  result 
:=   self.Count  =  0  ;
 end;
 
 
{ ClassUseLifo }
 
 
constructor   ClassUseLifo.Create  ;
 begin
  inherited;
 end;
 
 procedure  
ClassUseLifo.DepilerListener(  Sender:   TObject  ;   s  :string  )  ;
 begin
  
writeln  (  'On a depile : '  ,s)  ;
 end;
 
 procedure  
ClassUseLifo.EmpilerListener(  Sender:   TObject  ;   s  :string  )  ;
 begin
  
writeln  (  'On a empile : '  ,s)  ;
 end;
 
 procedure  
ClassUseLifo.main  ;
 var
  
pileLifo  :  ClassLifo  ;
  
ch  :string  ;
  begin
   
pileLifo  :=  ClassLifo.Create  ;
   
pileLifo.OnEmpiler  :=   EmpilerListener  ;
   
pileLifo.OnDepiler  :=   DepilerListener  ;
   
pileLifo.Empiler(  '[ eau ]'  )  ;
   
pileLifo.Empiler(  '[ terre ]'  )  ;
   
pileLifo.Empiler(  '[ mer ]'  )  ;
   
pileLifo.Empiler(  '[ voiture ]'  )  ;
   
writeln  (  'Depilement de la pile :'  )  ;
   while  
not   pileLifo.Est_Vide   do
   begin
    
pileLifo.Depiler(ch)  ;
    
writeln  (ch)  ;
   end;
   
writeln  (  'Fin du depilement.'  )  ;
   
readln  ;
  end;
  
end.