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!
newkeyword 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 wasvirtualfor the base class andòverridein the derived class...