0

このコードは機能しませんが、ここで達成しようとしていることが理解できることを願っています。http://www.noticeablydifferent.com/CodeSamples/Money.aspxから取得した Money クラスを取得し、通貨変換を含めるために少し拡張しました。

実際のコンバージョン率の実装はプロジェクトごとに異なる可能性があるため、コンバージョン率を取得するための実際のメソッド (GetCurrencyConversionRate) を派生クラスに移動することにしましたが、ConvertTo メソッドには、派生クラスを想定した任意の実装で機能するコードが含まれています。クラスは GetCurrencyConversionRate をオーバーライドしたので、親クラスに保持することは理にかなっていますか? だから私がしようとしているのは、SubMoney のインスタンスを取得し、.ConvertTo() メソッドを呼び出すことができるようにすることです。これにより、オーバーライドされた GetCurrencyConversionRate が使用され、SubMoney の新しいインスタンスが返されます。

問題は、ポリモーフィズムと継承のいくつかの概念をまだ本当に理解していないことです。そのため、現在起こっていることは、私が最終的に派生メソッドの代わりにベース GetCurrencyConversionRate メソッドを使用した場合に例外が発生します。ConvertTo メソッドを派生クラスに移動する必要があるとのことですが、これは複数の実装でコードを複製することになるので、もっと良い方法があるのではないでしょうか?

public class Money
{
    public CurrencyConversionRate
    {
        get
        {
            return GetCurrencyConversionRate(_regionInfo.ISOCurrencySymbol);
        }
    }

    public static decimal GetCurrencyConversionRate(string isoCurrencySymbol)
    {
        throw new Exception("Must override this method if you wish to use it.");
    }

    public Money ConvertTo(string cultureName)
    {          
        // convert to base USD first by dividing current amount by it's exchange rate.
        Money someMoney = this;
        decimal conversionRate = this.CurrencyConversionRate;
        decimal convertedUSDAmount = Money.Divide(someMoney, conversionRate).Amount;

        // now convert to new currency
        CultureInfo cultureInfo = new CultureInfo(cultureName);
        RegionInfo regionInfo = new RegionInfo(cultureInfo.LCID);
        conversionRate = GetCurrencyConversionRate(regionInfo.ISOCurrencySymbol);
        decimal convertedAmount = convertedUSDAmount * conversionRate;
        Money convertedMoney = new Money(convertedAmount, cultureName);
        return convertedMoney;
    }
}

public class SubMoney
{
    public SubMoney(decimal amount, string cultureName) : base(amount, cultureName) {}

    public static new decimal GetCurrencyConversionRate(string isoCurrencySymbol)
    {
        // This would get the conversion rate from some web or database source
        decimal result = new Decimal(2);
        return result;
    }
}
4

4 に答える 4

3

静的メソッドは、それが宣言されている正確なクラスを指定することによってのみ使用できます。その中に継承を含める方法はありません。

クラスをMoney抽象化して、使用するために派生する必要があるようにします。GetCurrencyConversionRate メソッドを抽象化します (自動的に仮想化します)。クラスがメソッドSubMoneyを継承Moneyしてオーバーライドするようにします。GetCurrencyConversionRate

public abstract class Money {

  public abstract decimal GetCurrencyConversionRate(string isoCurrencySymbol);

  ...

}

public class SubMoney : Money {

  public override decimal GetCurrencyConversionRate(string isoCurrencySymbol) {
    ...
  }

}

メソッドはMoneyクラスで宣言されているため、それを認識して使用できます。インスタンスを作成する実際のクラスは派生クラスなSubMoneyので、常にメソッドの実装があります。

于 2010-05-17T11:32:10.037 に答える
2

別のオプションは、Strategy Patternを使用することです。これにより、独自のクラスとして実装される変換のアルゴリズムを抽象化します。その後、実行時にコンバーターの実装を切り替えることができます。これにより、何らかの形式の依存性注入を使用して実行時にアルゴリズムを交換することにより、 「継承よりも構成」を利用できます。

複雑なシステムを設計した後、継承よりも合成の方が優れていることを確実に学びました。率直に言って、継承が真に役立つのは、ポリモーフィズムによってコードの再利用を増やすことが目標である場合だけです。継承チェーンの深さが 4 ~ 5 レベルを超える複雑な型階層に入ると、分野横断的な問題で頭がぶつかり合うことになります (これは、兄弟型間で共有できない非常に類似したコードの多くのコピーペーストにつながります)。コンポジションは、よりシンプルなデザイン、設定の容易さ (xaml を使用して WPF で複雑なフォームをデザインすることを考えてください)、テストなどを可能にします。

とにかく、頭を悩ませる何かを与えるためだけに。

于 2010-05-17T11:41:32.167 に答える
1

継承/オーバーライドをまったく使用していないため、メソッドを隠しています。

public abstract class Money
{
    public CurrencyConversionRate
    {
        get
        {
            return GetCurrencyConversionRate(_regionInfo.ISOCurrencySymbol);
        }
    }

    public abstract decimal GetCurrencyConversionRate(string isoCurrencySymbol);

    public Money ConvertTo(string cultureName)
    {          
        // convert to base USD first by dividing current amount by it's exchange rate.
        Money someMoney = this;
        decimal conversionRate = this.CurrencyConversionRate;
        decimal convertedUSDAmount = Money.Divide(someMoney, conversionRate).Amount;

        // now convert to new currency
        CultureInfo cultureInfo = new CultureInfo(cultureName);
        RegionInfo regionInfo = new RegionInfo(cultureInfo.LCID);
        conversionRate = GetCurrencyConversionRate(regionInfo.ISOCurrencySymbol);
        decimal convertedAmount = convertedUSDAmount * conversionRate;
        Money convertedMoney = new Money(convertedAmount, cultureName);
        return convertedMoney;
    }
}

public class SubMoney : Money
{
    public SubMoney(decimal amount, string cultureName) : base(amount, cultureName) {}

    public override decimal GetCurrencyConversionRate(string isoCurrencySymbol)
    {
        // This would get the conversion rate from some web or database source
        decimal result = new Decimal(2);
        return result;
    }
}

メソッドを抽象として宣言する場合、継承クラスはこのメソッドをオーバーライドする必要があります。これにより、カスタム コードが強制されます。もちろん、SubMoney クラスはこれを行うために Money を継承する必要があります。

于 2010-05-17T11:31:27.900 に答える
0

GetCurrencyConversionRate静的です。オーバーライドできません。

于 2010-05-17T11:32:41.940 に答える