2016-07-29 12 views
0

Ich gehe durch Kopf zuerst Design-Muster, aber ich codiere die Beispiele in C# anstelle von Java. Ich habe ein Decorator-Muster programmiert, aber ich bekomme einen seltsamen Fehler, den ich nicht herausfinden kann. Zeile 1 läuft wie erwartet, und die Beschreibung ist "Dark Roast", aber Zeile zwei ändert die Beschreibung zu "unbekanntes Getränk" statt der erwarteten "Dark Roast, Mocha." Wie behebe ich dieses Verhalten?C# Vererbung verhält sich nicht so, wie ich es erwarte

Hauptprogramm:

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

Decorator Code:

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

Hauptprogramm d Kompiliert nicht. – Ian

Antwort

3

Sie haben nicht die Description Eigenschaft als virtual in der Beverage Klasse markiert. Wenn also Ihre Variable beverage eine Beverage ist, wird die Description Eigenschaft immer von dort gelesen. Der Wert ist immer der Standard unbekannt.

Entfernen Sie einfach die abstract Deklaration aus der CondimentDecorator Klasse und fügen Sie virtual zur Basisklasse hinzu, dann funktioniert Ihre Überschreibung.

+0

Perfekt, danke! Ich habe es abstrakt gehalten, weil die Idee darin besteht, die Klassen, die es implementieren, dazu zu bringen, die Implementierung zu schreiben. Danke für das Zeigen und Erklären des Problems. – haosmark

+0

Was ist der Sinn der 'CondimentDecorator' Klasse, wenn Sie' abstract' Eigenschaft daraus entfernen? Wenn dies der Fall ist, können Sie 'CondimentDecorator' vollständig entfernen und' Mocha' direkt von 'Beverage' erben und trotzdem das gleiche Ergebnis erzielen. –

1

Sie die ursprüngliche Description Eigenschaft in CondimentDecorator versteckt, eine neue Eigenschaft Description oben drauf zu machen, wenn Sie den Typ auf einen CondimentDecorator ändern, dann werden Sie das erwartete Ergebnis.

Dieser Wert drucken sollten Sie erwarten:

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

Sie müssen die Basis ändern, abstrakt oder virtuell zu sein und es auf die Vererbungsklassen außer Kraft setzen

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

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

An dieser Stelle Sie don keine zusätzliche Dekoratorklasse benötigen, überschreiben Sie einfach die Methode im Stammobjekt

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