クラスを使って変換を管理する
RTL の利用:インデックス への移動
変換関数を使用すれば,どの変換単位も登録できます。しかし,場合によっては,ほぼ同じことを実行する関数を不要に大量に作成しなければならないことがあります。
パラメータか変数の値だけが異なる複数の変換関数をひとまとめにして記述できれば,クラスを 1 つ作成するだけで複数の変換を処理できます。たとえば欧州通貨の場合,ユーロの導入後,欧州各国通貨の変換を行うための基準設定手法が使用されています。(ドルとユーロの間などで変換するのと異なり)変換係数は従来どおり一定ですが,単純な変換係数を使用するだけでは,欧州各国の通貨間で正しく変換することはできません。その理由は次のとおりです。
- 変換後の丸めの桁数が通貨によって異なる
- 変換係数を使用する変換は,ユーロ変換基準が指定している係数に対して逆の係数を使用する
しかし,以下のように変換関数によりすべて処理できます。
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);
}
この方法には問題が 1 つあります。それは,変換関数に対してパラメータが新たに必要になることです。つまり,各欧州通貨に対して単に同じ関数を登録するだけでは正しく変換できません。欧州通貨ごとに変換関数を 2 つずつ新規作成する労力をはぶくには,同じ 2 つの関数を同一クラスのメンバーとして利用します。
目次 |
変換クラスを作成する
変換クラスは,TConvTypeFactor から派生させます。TConvTypeFactor は,2 つのメソッド(ToCommon と FromCommon)を定義しています。これにより,変換ファミリーの基本単位からの変換と,基本単位への変換(この例ではユーロとの変換)を行います。変換単位の登録時に使用する関数と同様に,これらのメソッドも追加のパラメータを持ちません。したがって,作成する変換クラスのプライベートメンバーとして,四捨五入の桁数や変換係数を自分で指定する必要があります。下に例を示します。
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);
}
次のように,コンストラクタがプライベートメンバーに値を割り当てます。
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;
}
下に示すように,2 つの変換関数は単に上記のプライベートメンバーを使用するだけです。
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);
}
変数を宣言する
以上で変換クラスが作成できました。今度は,識別子を宣言して新しい変換ファミリーを登録します。
var
euEUR: TConvType; { EU ユーロ }
euBEF: TConvType; { ベルギーフラン }
euDEM: TConvType; { ドイツマルク }
euGRD: TConvType; { ギリシャドラクマ }
euESP: TConvType; { スペインペセタ }
euFFR: TConvType; { フランスフラン }
euIEP: TConvType; { アイルランドポンド }
euITL: TConvType; { イタリアリラ }
euLUF: TConvType; { ルクセンブルグフラン }
euNLG: TConvType; { オランダギルダー }
euATS: TConvType; { オーストリアシリング }
euPTE: TConvType; { ポルトガルエスクード }
euFIM: TConvType; { フィンランドマルッカ }
cbEuro: TConvFamily;
TConvFamily cbEuro; TConvType euEUR; // EU ユーロ TConvType euBEF; // ベルギーフラン TConvType euDEM; // ドイツマルク TConvType euGRD; // ギリシャドラクマ TConvType euESP; // スペインペセタ TConvType euFFR; // フランスフラン TConvType euIEP; // アイルランドポンド TConvType euITL; // イタリアリラ TConvType euLUF; // ルクセンブルグフラン TConvType euNLG; // オランダギルダー TConvType euATS; // オーストリアシリング TConvType euPTE; // ポルトガルエスクード TConvType euFIM; // フィンランドマルッカ
変換ファミリーおよびほかの単位を登録する
新規作成した変換クラスを使用して,変換ファミリーおよび欧州各国の通貨単位を登録します。ほかの変換ファミリーを登録したときとまったく同じように変換ファミリーを登録します。
cbEuro := RegisterConversionFamily ('European currency');
cbEuro = RegisterConversionFamily ("European currency");
各変換型を登録するには,通貨の係数と丸めのプロパティを反映した変換クラスのインスタンスを作成し,RegisterConversionType メソッドを呼び出します。
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;
メモ: [スタート|すべてのプログラム|Embarcadero RAD Studio|サンプル] をクリックすると,(Delphi\RTL\ConvertIt および \CPP\RTL\ConvertIt 以下に)ConvertIt サンプルがあります。ConvertIt サンプルでは,上記以外の通貨(固定の変換レートを持たない通貨)にも対応しているほか,エラーチェックも拡張されています。
新しい単位を使用する
この段階で,新規登録した単位を使ってアプリケーション内で変換を実行できます。新しい変換ファミリー cbEuro に登録した欧州通貨どうしであれば,どれでもグローバル関数 Convert で変換ができます。イタリアリラからドイツマルクに変換するコード例を下に示します。
Edit2.Text = FloatToStr(Convert(StrToFloat(Edit1.Text), euITL, euDEM));
Edit2->Text = FloatToStr(Convert(StrToFloat(Edit1->Text), euITL, euDEM));