RAD Studio
|
You can always use conversion functions to register a conversion unit. There are times, however, when this requires you to create an unnecessarily large number of functions that all do essentially the same thing.
If you can write a set of conversion functions that differ only in the value of a parameter or variable, you can create a class to handle those conversions. For example, there is a set standard techniques for converting between the various European currencies since the introduction of the Euro. Even though the conversion factors remain constant (unlike the conversion factor between, say, dollars and Euros), you can't use a simple conversion factor approach to properly convert between European currencies for two reasons:
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;
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); }
The problem is, this approach requires extra parameters on the conversion function, which means you can't simply register the same function with every European currency. In order to avoid having to write two new conversion functions for every European currency, you can make use of the same two functions by making them the members of a class.
The class must be a descendant of TConvTypeFactor. TConvTypeFactor defines two methods, ToCommon and FromCommon, for converting to and from the base units of a conversion family (in this case, to and from Euros). Just as with the functions you use directly when registering a conversion unit, these methods have no extra parameters, so you must supply the number of digits to round off and the conversion factor as private members of your conversion class:
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;
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); }
The constructor assigns values to those private members:
constructor TConvTypeEuroFactor.Create(const AConvFamily: TConvFamily; const ADescription: string; const AFactor: Double; const ARound: TRoundToRange); begin inherited Create(AConvFamily, ADescription, AFactor); FRound := ARound; end;
__fastcall TConvTypeEuroFactor::TConvTypeEuroFactor(const TConvFamily AConvFamily, const AnsiString ADescription, const double AFactor, const TRoundToRange ARound): TConvTypeFactor(AConvFamily, ADescription, AFactor); { FRound = ARound; }
The two conversion functions simply use these private members:
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;
virtual double TConvTypeEuroFactor::ToCommon(const double AValue) { return (RoundTo(AValue * Factor, FRound)); } virtual double TConvTypeEuroFactor::ToCommon(const double AValue) { return (AValue / Factor); }
Now that you have a conversion class, begin as with any other conversion family, by declaring identifiers:
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;
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
Now you are ready to register the conversion family and the European monetary units, using your new conversion class. Register the conversion family the same way you registered the other conversion families:
cbEuro := RegisterConversionFamily ('European currency');
cbEuro = RegisterConversionFamily ("European currency");
To register each conversion type, create an instance of the conversion class that reflects the factor and rounding properties of that currency, and call the RegisterConversionType method:
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;
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;
You can now use the newly registered units to perform conversions in your applications. The global Convert function can convert between any of the European currencies you have registered with the new cbEuro family. For example, the following code converts a value from Italian Lire to German Marks:
Edit2.Text = FloatToStr(Convert(StrToFloat(Edit1.Text), euITL, euDEM));
Edit2->Text = FloatToStr(Convert(StrToFloat(Edit1->Text), euITL, euDEM));
Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
|
What do you think about this topic? Send feedback!
|