C#继承没有';Don’别按我的期望行事

本文关键字:我的 期望 Don 继承 | 更新日期: 2023-09-27 17:59:19

我正在从头开始设计模式,但我正在用C#而不是java编写示例。我编码了decorator模式,但我遇到了一些奇怪的错误,我不知道如何修复。第1行按预期运行,描述为"Dark Roast",但第2行将描述改为"未知饮料",而不是预期的"Dark Burst,Mocha"。如何修复这种行为?

主程序:

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#继承没有';Don’别按我的期望行事

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

只需从CondimentDecorator类中删除abstract声明,并将virtual添加到基类中,那么您的覆盖就可以工作了。

您将原始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";
}

此时,您不需要额外的decorator类,只需覆盖基础对象中的方法即可

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