Why is my object still using the method, although I overcame it?

Possible repeat : Why is my virtual method not overestimated?

I am looking at First First Design templates. On the other hand, I started this book as a prerequisite for Code Complete 2. In any case, I work with the Decorator template (the chapter can even be read online) .

So, I have 4 classes:

  • Beverage Class - Abstract
  • Espresso Class - Inheritance of Beverages
  • Dececorator Drink Class - Abstract
  • Mocha Class - Inherits Decotrator for Beverages

Here is the source code for classes 1, 3, 4.

Beverage Class:

public abstract class Beverage { public Beverage() { Description = "Unknown Beverage"; } public String getDescription() { return Description; } public abstract double cost(); public String Description { get; set; } } 

Beverage Class Decorator:

  public abstract class BeverageDecorator : Beverage { public new abstract String getDescription(); } 

Mocha Class:

  public class Mocha : BeverageDecorator { Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.Description + ", Mocha"; } public override double cost() { return beverage.cost() + .20; } } 

So, they are pretty straightforward. Then, when I put this code in the Main () method, I continue to get the description "Unknown drink."

  static void Main(string[] args) { Beverage beverage = new Espresso(); beverage = new Mocha(beverage); Console.WriteLine(beverage.Description + " $" + beverage.cost()); Console.Read(); } 

Mocha is moving from the class he inherits - the Decorator for drinks - to a class above that - the drinks class. Although I have a method in Decorator for drinks and I redefine it. Why is this happening? I know this has something to do with abstract classes, but I just can't figure it out.

+4
source share
3 answers

Well, there are two problems. First, it looks like your Description property should call getDescription , and not vice versa. And then getDescription should be virtual in the Beverage class and redefined in BeverageDecorator , and not hidden.

This does not help to make your code look like a mixture of C # and Java. For example, do you really need the Description property and getDescription method? Admittedly, it's a bit difficult to override half the property (at least I'm always confused with the exact rules), but it is definitely weird to have camelCased names in C # code.

Here's an alternative implementation (there is no decorator class - it's unclear how this should have helped):

 using System; public abstract class Beverage { public Beverage() { Description = "Unknown Beverage"; } private string description; public virtual string Description { get { return description; } set { description = value; } } } public class Espresso : Beverage { public Espresso() { Description = "Espresso"; } } public class Mocha : Beverage { private readonly Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } public override string Description { get { return beverage.Description + ", Mocha"; } set { /* Ignored */ } } } public class Test { static void Main() { Beverage espresso = new Espresso(); Beverage mocha = new Mocha(espresso); Console.WriteLine(mocha.Description); // Prints Espresso, Mocha } } 
+2
source

You did not really turn it over. You used the new operator to hide the element below it. One problem with this statement is that if the caller uses a reference to a type that contains an element that is hidden later, it bypasses the hide. In your case, when you use Beverage and expect to see an overridden result:

 Beverage beverage = new Espresso(); beverage = new Mocha(beverage); Console.WriteLine(beverage.Description + " $" + beverage.cost()); 

To override something, something must be virtual or abstract , and the overriding element needs to use override . Your member is not abstract or virtual, but in the derived class you have new string getDescription not override string getdescription .

So, in your code, when you talk to Beverage , it ignores the hiding done in BeverageDecorator .

A larger discussion of the decorator pattern, the decoration class does not need to be inherited from what it decorates. This is usually done if the decorated class is a design parameter. If you need decoration, as well as some polymorphism, consider using the interface in combination with it:

 interface ICommonStuff { string getDescription(); } public class Beverage : ICommonStuff { } public class BeverageDecorator : ICommonStuff { public BeverageDecorator(Beverage b) { } } 

But then do you really need decoration? This is what I often ask during the holidays ...

+5
source

public new abstract String getDescription ();

This is not a method override, it is a new method that is not associated with the getDescription method in the base class.

Beverage.getDescription cannot be overridden because it is not virtual. Instead, declare this:

 public abstract String getDescription(); 

or so:

 public virtual String getDescription() { return Description; } 
+2
source

All Articles