Utilisation d'une classe pour gérer les conversions

De Appmethod Topics
Aller à : navigation, rechercher

Remonter à Utilisation de la RTL - Index


Vous pouvez toujours utiliser des fonctions de conversion pour recenser une unité de conversion. Il existe cependant des cas où il est nécessaire de créer un nombre inutilement grand de fonctions qui font toutes essentiellement la même chose.

Si vous pouvez écrire un ensemble de fonctions de conversion qui diffèrent uniquement par la valeur d'un paramètre ou d'une variable, vous pouvez créer une classe pour gérer ces conversions. Par exemple, il existe un ensemble de techniques standard pour les conversions entre les différentes monnaies européennes depuis l'introduction de l'euro. Bien que les facteurs de conversion restent constants (contrairement au facteur de conversion entre les dollars et les euros, par exemple), vous ne pouvez pas utiliser un facteur de conversion simple pour convertir correctement les monnaies européennes, pour deux raisons :

  • La conversion doit arrondir à un nombre de décimales spécifique à la monnaie.
  • L'approche facteur de conversion utilise un facteur inverse à celui spécifié par les conversions standard en euro.

Tout peut cependant être géré par les fonctions de conversion de la façon suivante :

Object Pascal :

 function FromEuro(const AValue: Double, Factor; FRound: TRoundToRange): Double;
 begin
   Result := RoundTo(AValue * Factor, FRound);
 end;
 function ToEuro(const AValue: Double, Factor): Double;
 begin
   Result := AValue / Factor;
 end;

C++ :

double __fastcall FromEuro(const double AValue, const double Factor,
    TRoundToRange FRound) {
    return(RoundTo(AValue * Factor, FRound));
}

double __fastcall ToEuro(const double AValue, const double Factor) {
    return (AValue / Factor);
}

Le problème est que cette approche nécessite des paramètres supplémentaires pour la fonction de conversion, ce qui signifie que vous ne pouvez pas recenser simplement la même fonction pour chaque monnaie européenne. Afin d'éviter d'écrire deux nouvelles fonctions de conversion pour chacune des monnaies européennes, vous pouvez utiliser le même couple de fonctions en les rendant membres d'une classe.

Création de la classe de conversion

La classe doit être un descendant de TConvTypeFactor. TConvTypeFactor définit deux méthodes, ToCommon et FromCommon, pour convertir à destination et à partir des unités de base d'une famille de conversion (dans ce cas, à destination et à partir des euros). Comme les fonctions que vous utilisez directement pour le recensement d'une unité de conversion, ces méthodes n'ont pas de paramètres supplémentaires, et vous devez fournir le nombre de décimales de l'arrondi et le facteur de conversion en tant que membres privés de votre classe de conversion. Ce point est illustré dans l'exemple EuroConv du répertoire demos\ConvertIt (voir euroconv.pas) :

Object Pascal :

 type
 TConvTypeEuroFactor = class(TConvTypeFactor)
 private
 FRound: TRoundToRange;
 public
 constructor Create(const AConvFamily: TConvFamily;
 const ADescription: string; const AFactor: Double;
 const ARound: TRoundToRange);
 function ToCommon(const AValue: Double): Double; override;
 function FromCommon(const AValue: Double): Double; override;
 end;
 end;

C++ :

class PASCALIMPLEMENTATION TConvTypeEuroFactor
		: public Convutils::TConvTypeFactor {
private:
	TRoundToRange FRound;

public:
	__fastcall TConvTypeEuroFactor(const TConvFamily AConvFamily,
			const AnsiString ADescription, const double AFactor,
			const TRoundToRange ARound);
	TConvTypeFactor(AConvFamily, ADescription, AFactor);
	virtual double ToCommon(const double AValue);
	virtual double FromCommon(const double AValue);
}

Le constructeur attribue des valeurs à ces membres privés :

Object Pascal :

 constructor TConvTypeEuroFactor.Create(const AConvFamily: TConvFamily; const ADescription: string; const AFactor: Double; const ARound: TRoundToRange);
 begin
   inherited Create(AConvFamily, ADescription, AFactor);
   FRound := ARound;
 end;

C++ :

__fastcall TConvTypeEuroFactor::TConvTypeEuroFactor
    (const TConvFamily AConvFamily, const AnsiString ADescription,
    const double AFactor, const TRoundToRange ARound)
    : TConvTypeFactor(AConvFamily, ADescription, AFactor); {
    FRound = ARound;
}

Les deux fonctions de conversion utilisent simplement ces membres privés :

Object Pascal :

 function TConvTypeEuroFactor.FromCommon(const AValue: Double): Double;
 begin
   Result := RoundTo(AValue * Factor, FRound);
 end;
 function TConvTypeEuroFactor.ToCommon(const AValue: Double): Double;
 begin
   Result := AValue / Factor;
 end;

C++ :

virtual double TConvTypeEuroFactor::ToCommon(const double AValue) {
    return (RoundTo(AValue * Factor, FRound));
}

virtual double TConvTypeEuroFactor::ToCommon(const double AValue) {
    return (AValue / Factor);
}

Déclaration des variables

Maintenant que vous disposez d'une classe de conversion, commencez comme avec toute autre famille de conversion, en déclarant les identificateurs :

Object Pascal :

 var
   euEUR: TConvType; { EU euro }
 euBEF: TConvType; { Belgian francs }
 euDEM: TConvType; { German marks }
 euGRD: TConvType; { Greek drachmas }
 euESP: TConvType; { Spanish pesetas }
 euFFR: TConvType; { French francs }
 euIEP: TConvType; { Irish pounds }
 euITL: TConvType; { Italian lire }
 euLUF: TConvType; { Luxembourg francs }
 euNLG: TConvType; { Dutch guilders }
 euATS: TConvType; { Austrian schillings }
 euPTE: TConvType; { Portuguese escudos }
 euFIM: TConvType; { Finnish marks }
   cbEuro: TConvFamily;

C++ :

TConvFamily cbEuro;
TConvType euEUR; // EU euro
TConvType euBEF; // Belgian francs
TConvType euDEM; // German marks
TConvType euGRD; // Greek drachmas
TConvType euESP; // Spanish pesetas
TConvType euFFR; // French francs
TConvType euIEP; // Irish pounds
TConvType euITL; // Italian lire
TConvType euLUF; // Luxembourg francs
TConvType euNLG; // Dutch guilders
TConvType euATS; // Austrian schillings
TConvType euPTE; // Protuguese escudos
TConvType euFIM; // Finnish marks

Recensement de la famille de conversion et des autres unités

Vous êtes maintenant prêt à recenser la famille de conversion et les unités monétaires européennes, en utilisant votre nouvelle classe de conversion. Recensez cette famille de conversion de la même manière que vous avez recensé les autres :

Object Pascal :

 cbEuro := RegisterConversionFamily ('European currency');

C++ :

cbEuro = RegisterConversionFamily("European currency");

Pour recenser chaque type de conversion, créez une instance de la classe de conversion qui reflète les propriétés de facteur et d'arrondi de cette monnaie, et appelez la méthode RegisterConversionType :

Object Pascal :

 var
   LInfo: TConvTypeInfo;
 begin
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'EUEuro', 1.0, -2);
   if not RegisterConversionType(LInfo, euEUR) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'BelgianFrancs', 40.3399, 0);
   if not RegisterConversionType(LInfo, euBEF) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'GermanMarks', 1.95583, -2);
   if not RegisterConversionType(LInfo, euDEM) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'GreekDrachmas', 340.75, 0);
   if not RegisterConversionType(LInfo, euGRD) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'SpanishPesetas', 166.386, 0);
   if not RegisterConversionType(LInfo, euESP) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'FrenchFrancs', 6.55957, -2);
   if not RegisterConversionType(LInfo, euFFR) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'IrishPounds', 0.787564, -2);
   if not RegisterConversionType(LInfo, euIEP) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'ItalianLire', 1936.27, 0);
   if not RegisterConversionType(LInfo, euITL) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'LuxembourgFrancs', 40.3399, -2);
   if not RegisterConversionType(LInfo, euLUF) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'DutchGuilders', 2.20371, -2);
   if not RegisterConversionType(LInfo, euNLG) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'AustrianSchillings', 13.7603, -2);
   if not RegisterConversionType(LInfo, euATS) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'PortugueseEscudos', 200.482, -2);
   if not RegisterConversionType(LInfo, euPTE) then
     LInfo.Free;
   LInfo := TConvTypeEuroFactor.Create(cbEuro, 'FinnishMarks', 5.94573, 0);
   if not RegisterConversionType(LInfo, euFIM) then
     LInfo.Free;
 end;

C++ :

TConvTypeInfo *pInfo = new TConvTypeEuroFactor(cbEuro, " EUEuro ", 1.0, -2);
if (!RegisterConversionType(pInfo, euEUR))
	delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " BelgianFrancs ", 40.3399, 0);
if (!RegisterConversionType(pInfo, euBEF))
	delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " GermanMarks ", 1.95583, -2);
if (!RegisterConversionType(pInfo, euDEM))
	delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " GreekDrachmas ", 340.75, 0);
if (!RegisterConversionType(pInfo, euGRD) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " SpanishPesetas ", 166.386, 0);
if (!RegisterConversionType(pInfo, euESP) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " FrenchFrancs ", 6.55957, -2);
if (!RegisterConversionType(pInfo, euFFR) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " IrishPounds ", 0.787564, -2);
if (!RegisterConversionType(pInfo, euIEP) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " ItalianLire ", 1936.27, 0);
if (!RegisterConversionType(pInfo, euITL) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " LuxembourgFrancs ", 40.3399, -2);
if (!RegisterConversionType(pInfo, euLUF) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " DutchGuilders ", 2.20371, -2);
if (!RegisterConversionType(pInfo, euNLG) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " AutstrianSchillings ", 13.7603, -2);
if (!RegisterConversionType(pInfo, euATS) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " PortugueseEscudos ", 200.482, -2);
if (!RegisterConversionType(pInfo, euPTE) delete pInfo;
pInfo = new TConvTypeEuroFactor(cbEuro, " FinnishMarks ", 5.94573, 0);
if (!RegisterConversionType(pInfo, euFIM) delete pInfo;

Remarque : Cliquez sur Démarrer | Programmes | Appmethod 1.15 | Exemples pour trouver l'exemple ConvertIt (voir Object Pascal\RTL\ConvertIt et \CPP\RTL\ConvertIt). L'exemple ConvertIt étend cet exemple à d'autres devises (dont le taux de conversion n'est pas fixe) et propose davantage de vérification d'erreur.

Utilisation des nouvelles unités

Vous pouvez maintenant utiliser les unités que vous venez de recenser pour effectuer des conversions dans vos applications. La fonction Convert globale peut convertir toutes les monnaies européennes que vous avez recensées avec la nouvelle famille cbEuro. Par exemple, le code suivant convertit en marks allemands une valeur exprimée en lires italiennes :

C++ :

Edit2->Text = FloatToStr(Convert(StrToFloat(Edit1->Text), euITL, euDEM));

Voir aussi