【问题标题】:C# inheritance doesn't behave as I expect it toC# 继承的行为不像我预期的那样
【发布时间】:2016-12-04 16:10:21
【问题描述】:

我正在研究头部优先设计模式,但我正在用 C# 而不是 java 编写示例。我编写了装饰器模式,但我遇到了一些奇怪的错误,我无法弄清楚如何修复。 第 1 行按预期运行,描述为“Dark Roast”,但第 2 行将描述更改为“未知饮料”,而不是预期的“Dark Roast,摩卡”。如何解决此问题?

主程序:

beverage = new DarkRoast();
beverage = new Mocha(beverage);
beverage = new Mocha(beverage);
Console.WriteLine(beverage.Description + " $" + beverage.Cost);

装饰器代码:

namespace DecoratorPattern
{
    public abstract class Beverage
    {
        public abstract double Cost { get; }

        public string Description { get; set; } = "unknown beverage";
    }

    public class DarkRoast : Beverage
    {
        public DarkRoast()
        {
            Description = "Dark Roast";
        }

        public override double Cost => .99;
    }

    public abstract class CondimentDecorator : Beverage
    {
        public abstract string Description { get; }
    }

    public class Mocha : CondimentDecorator
    {
        Beverage beverage;

        public Mocha(Beverage beverage)
        {
            this.beverage = beverage;
        }

        public override string Description
        {
            get { return beverage.Description + ", Mocha"; }
        }

        public override double Cost => .20 + beverage.Cost;
    }
}

【问题讨论】:

  • 主程序无法编译。

标签: c# inheritance decorator


【解决方案1】:

您尚未在 Beverage 类中将 Description 属性标记为 virtual。因此,如果您的变量beverageBeverage,则将始终从那里读取Description 属性。该值将始终为默认未知值。

只需从CondimentDecorator 类中删除abstract 声明并将virtual 添加到基类中,然后您的覆盖将起作用。

【讨论】:

  • 完美,谢谢!我保持它是抽象的,因为这个想法是强制实现它的类写出实现。感谢您指出并解释问题。
  • 那么如果你从中删除abstract 属性,那么CondimentDecorator 类的意义何在?如果是这样,您可以完全删除 CondimentDecorator 并直接从 Beverage 继承 Mocha 并且仍然得到相同的结果。
【解决方案2】:

您将原来的Description 属性隐藏在CondimentDecorator 中,在其上创建一个新属性Description,如果您将类型更改为CondimentDecorator,那么您将获得预期的结果。

这应该会打印出您期望的值:

 var result = (CondimentDecorator) beverage;
 Console.WriteLine(result.Description);

您需要将基础更改为抽象或虚拟并在继承类上覆盖它

public abstract class Beverage
{
    public abstract double Cost { get; }

    public virtual Description { get; set; } = "unknown beverage";
}

此时你不需要额外的装饰器类,只需覆盖基础对象中的方法

public class Mocha : Beverage
{
    Beverage beverage;

    public Mocha(Beverage beverage)
    {
        this.beverage = beverage;
    }

    public override string Description
    {
        get { return beverage.Description + ", Mocha"; }
        set { throw InvalidOperationException("Cannot Set Value of Decorator"); }
    }

    public override double Cost => .20 + beverage.Cost;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2020-03-11
    • 2016-01-28
    • 2018-12-15
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    相关资源
    最近更新 更多