I'm working through the Head First Design Patterns book and am currently on the Decorator Pattern chapter. Since the book examples are written in Java, I'm adapting the, to C# as I go.
This example simulates a coffee shop ordering system. There is an abstract base class for Beverage
and subclasses for specific beverages (ex: Espresso
). The decorator classes are used to add condiments and drink modifications. There is an abstract class CondimentDecorator
that derives from Beverage
and then subclasses like Mocha
for the individual decorators. Gist with all files: https://gist.github.com/anonymous/67e4fe5fe0477d34b24125f741ad0b3a
My question - in the base Beverage
class, the description string is set to "Unknown beverage". The constructor for a specific drink sets this to the drink name - so if I use:
Beverage espresso = new Espresso();
Console.WriteLine($"{espresso.GetDescription()}");
It responds with "Espresso". Now, when using the decorator, the GetDescription
method is overridden, in the Mocha
class it adds "Mocha" after the beverage's description.
public override string GetDescription()
{
return beverage.GetDescription() + " Mocha";
}
If I use the override
modifier in CondimentDecorator.cs:
public abstract override string GetDescription();
This works as expected. I run:
Beverage espresso = new Espresso();
Console.WriteLine($"{espresso.GetDescription()}"); // Espresso
espresso = new Mocha(espresso);
Console.WriteLine($"{espresso.GetDescription()}"); // Espresso Mocha
However, if I change the modifier to new
in CondimentDecorator.cs like this:
public abstract new string GetDescription();
And run the same code, I get the below results:
Beverage espresso = new Espresso();
Console.WriteLine($"{espresso.GetDescription()}"); // Espresso
espresso = new Mocha(espresso);
Console.WriteLine($"{espresso.GetDescription()}"); // Unknown beverage
I'm a little confused why this happens...since GetDescription
is being called in Mocha like this...
public override string GetDescription()
{
return beverage.GetDescription() + " Mocha";
}
...and beverage is a reference back to the original espresso object, why doesn't the code pick up on the description that was set when Espresso
was instantiated? The way I understand this, new
would hide the original GetDescription
method in the base class while override
would extend that method. I'm not sure why that would effect which description the program reads -- the "unknown beverage" of Mocha
, which gets that value from the Beverage
class it derives from, or the "Espresso" of the beverage object I created that had the description set in the constructor.
I'm sure I'm just misunderstanding something basic about inheritance and how the new and override keywords work, if anyone can shed a little light on this I'd appreciate it!
Thanks!
new
keyword with a method or property is most often wrong. Hardly anyone understands it, though there might be some rare uses for it. E.g. for our green field projects, I configured the Jenkins build to treat all warnings as errors. One of my colleagues used the same function name in a base class and its derived class which caused a fail. How did he fix that? By taking the suggestion of the compiler. Now the "bug in waiting" was changed to a real bug - the real solution wasvirtual
for the base class andòverride
in the derived class...