クラスを使用した変換の管理

提供: Appmethod Topics
移動先: 案内検索

RTL の使用:インデックス への移動

変換関数を使用すると、必ず変換単位を登録できます。ただし、そのために、基本的に同じことを行う関数を不必要に多数作成しなければならなくなる場合があります。

パラメータや変数の値のみ異なる一連の変換関数を作成できる場合は、それらの変換を処理するクラスを作成できます。たとえば、欧州通貨の場合、ユーロの導入以後、さまざまな欧州通貨間の変換を行うための一連の標準手法が用意されています。(たとえばドルとユーロの間の変換係数とは異なり)たとえ変換係数がそのまま変わらないとしても、単純な変換係数を使用するアプローチで欧州通貨間の変換を正しく行うことはできません。その理由は以下の 2 点です。

  • 変換結果の丸めの桁数が通貨によって異なる。
  • 変換係数を使用するアプローチでは、ユーロ変換基準で指定されている係数の逆数を係数として使用する。

しかし、これは、以下のような変換関数によりすべて処理できます。

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);
}

問題は、このアプローチでは変換関数にパラメータが新たに必要になることです。つまり、どの欧州通貨についても同じ関数を登録するだけで済むというわけにはいきません。欧州通貨ごとに新しい変換関数を 2 つずつ作成する手間を避けるには、それと同じ 2 つの関数を、あるクラスのメンバにすることで利用できます。

変換クラスの作成

このクラスは TConvTypeFactor の下位クラスでなければなりません。TConvTypeFactor には、ToCommonFromCommon の 2 つのメソッドが定義されており、それぞれ、変換ファミリの基本単位への変換と基本単位からの変換(この例ではユーロとの間の変換)を行います。変換単位の登録時に直接使用する関数の場合と同様に、これらのメソッドにも追加のパラメータはないため、丸めの桁数や変換係数を、作成する変換クラスの private メンバとして用意する必要があります。以下は、demos\ConvertIt ディレクトリに含まれている EuroConv サンプル(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);
}

以下のように、コンストラクタで private メンバに値が割り当てられます。

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;
}

以下のように、2 つの変換関数は上記の private メンバを使用するだけです。

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);
}

変数の宣言

これで変換クラスができたので、他のあらゆる変換ファミリの場合と同様に、まず識別子を宣言します。

Object Pascal の場合:

 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;

C++ の場合:

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; // フィンランド マルッカ

変換ファミリと他の単位の登録

これで、新規作成した変換クラスを使って、変換ファミリと欧州通貨単位を登録する用意ができました。他の変換ファミリの登録と同じように、この変換ファミリを登録します。

Object Pascal の場合:

 cbEuro := RegisterConversionFamily ('European currency');

C++ の場合:

cbEuro = RegisterConversionFamily("European currency");

各変換型を登録するには、以下のように、その通貨の係数と丸めのプロパティを反映した変換クラスのインスタンスを作成し、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;

メモ: [スタート | すべてのプログラム | Appmethod 1.15 | サンプル] をクリックすると、ConvertIt サンプルを見ることができます(Object Pascal\RTL\ConvertIt および \CPP\RTL\ConvertIt を参照)。ConvertIt サンプルは、この例を拡張したもので、変換レートが固定ではない他の通貨に対応しているほか、エラー チェックも追加されています。

新しい単位の使用

これで、新規登録した単位を使用して、アプリケーションで変換を実行できます。新規の cbEuro 変換ファミリに登録した欧州通貨単位どうしであれば、その間の変換はグローバル関数 Convert で実行できます。たとえば、以下のコードでは、値をイタリア リラからドイツ マルクに変換しています。

C++ の場合:

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

関連項目