0

这段代码不起作用,但希望你能在这里得到我想要实现的目标。我有一个 Money 类,我取自http://www.noticeablydifferent.com/CodeSamples/Money.aspx,并对其进行了一些扩展以包括货币转换。

实际转换率的实现在每个项目中可能不同,因此我决定将用于检索转换率 (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,您可以抽象转换算法,该算法被实现为它自己的类。然后,您可以在运行时切换转换器的实现。这允许您通过使用某种形式的依赖注入在运行时交换算法来利用“组合优于继承”

在设计了一个复杂的系统之后,我确实学到了组合优于继承的好处。坦率地说,只有当您的目标是通过多态性增加代码重用时,继承才真正有用。一旦你进入复杂的类型层次结构,其中继承链超过四到五个层次,你最终会遇到横切问题(这导致大量复制粘贴无法在同级类型之间共享的非常相似的代码)。组合允许更简单的设计、易于配置(考虑使用 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 回答