was trying to implement the Decorator pattern - for simplicity in this example we only have 1 concrete decorator named ConcreteDecorator1 and I got it to work, the example in functional. However my question is around OOP and more specifically I don't understand why I was getting a "component is null" exception on this line of the ConcreteDecorator1 : myField = this.myField + component.Operation();
BEFORE adding this.component = component
in the constructor of the same class?
I mean this.component = component
happens in the c-tor of the super class (Decorator) so why wasn't that enough?
class Program
{
static void Main(string[] args)
{
var cc = new ConcreteComponent();
cc.Operation();
Console.WriteLine(cc.myField);
var cd1 = new ConcreteDecorator1(cc);
cd1.Operation();
Console.WriteLine(cd1.myField);
var cd2 = new ConcreteDecorator1(cd1);
cd2.Operation();
Console.WriteLine(cd2.myField);
Console.ReadLine();
}
}
abstract class Component
{
public int myField;
public virtual int Operation()
{
return myField;
}
}
class ConcreteComponent : Component
{
public override int Operation()
{
myField = 22;
return myField;
}
}
class Decorator : Component
{
private Component component;
public Decorator(Component component)
{
this.component = component;
}
}
class ConcreteDecorator1 : Decorator
{
private Component component;
public ConcreteDecorator1(Component component) : base(component)
{
this.component = component; // WHY IS THIS LINE NECESSARY HERE? Don't we have it in the constructor of the base class, Decorator?
}
public override int Operation()
{
myField = 100;
myField = this.myField + component.Operation(); // error on this line: component was null ... UNLESS WE ADD this.component = component; in the c-tor WHy was this necessary? Doesn't the super class c-tor take care of it?
return myField;
}
}
So bottom line: why in the concrete decorator's constructor I have to repeat code of the superclass constructor? I thought I could leave it as this:
public ConcreteDecorator1(Component component) : base(component)
{
}
and potentially add in the body something extra, like additional logic, if needed (not needed here but just saying).
Later edit - Another working variant (Variant2):
class Program
{
static void Main(string[] args)
{
var cc = new ConcreteComponent();
cc.Operation();
Console.WriteLine(cc.myField);
var cd1 = new ConcreteDecorator1(cc);
cd1.Operation();
Console.WriteLine(cd1.myField);
var cd2 = new ConcreteDecorator1(cd1);
cd2.Operation();
Console.WriteLine(cd2.myField);
}
}
abstract class Component
{
public int myField;
public virtual int Operation()
{
return myField;
}
}
class ConcreteComponent : Component
{
public override int Operation()
{
myField = 22;
return myField;
}
}
class Decorator : Component
{
public Component Component { get; set; }
}
class ConcreteDecorator1 : Decorator
{
public ConcreteDecorator1(Component component)
{
this.Component = component;
}
public override int Operation()
{
myField = 100;
myField = this.myField + this.Component.Operation();
return myField;
}
}
Still not great, because I would rather define the Operation in the Decorator and in the concrete decorator I would just set the myField value...
Variant 3 (later update, also works):
abstract class Component
{
protected int myField;
public virtual int Operation()
{
return this.myField;
}
}
class ConcreteComponent : Component
{
public ConcreteComponent(int myField)
{
this.myField = myField;
}
}
class Decorator : Component
{
protected Component component;
public Decorator(Component component)
{
this.component = component;
}
public override int Operation()
{
this.myField = this.myField + component.Operation();
return myField;
}
}
class ConcreteDecorator1 : Decorator
{
public ConcreteDecorator1(Component component) : base(component)
{
this.myField = 100;
}
}
class ConcreteDecorator2 : Decorator
{
public ConcreteDecorator2(Component component) : base(component)
{
this.myField = 1000;
}
}
class Program
{
static void Main(string[] args)
{
var cc = new ConcreteComponent(22);
Console.WriteLine(cc.Operation());
//var cd1 = new ConcreteDecorator(cc, 100);
//cd1.Operation();
//Console.WriteLine(cd1.myField);
var cd2 = new ConcreteDecorator1(cc);
Console.WriteLine(cd2.Operation());
var cd3 = new ConcreteDecorator2(cd2);
Console.WriteLine(cd3.Operation());
Console.ReadLine();
}
}
You do not have to redefine a common object private Component component;
. Change the double definition of component as follows
class Decorator : Component
{
public Component component;
public Decorator(Component component)
{
this.component = component;
}
}
class ConcreteDecorator1 : Decorator
{
public ConcreteDecorator1(Component component) : base(component)
{
}
public override int Operation()
{
myField = 100;
myField = this.myField + component.Operation(); // error on this line: component was null ... UNLESS WE ADD this.component = component; in the c-tor WHy was this necessary? Doesn't the super class c-tor take care of it?
return myField;
}
}
With this code you only set the component of the parent class, not the component of this class. And when this code is executed myField = this.myField + component.Operation ();
The program gives a null error.
public ConcreteDecorator1(Component component) : base(component)
{
//This is wrong because the component is never set
}
Suppose you have two variables called x. You define one globally and the other locally within a function. You must use this keyword when you want to access the global variable.
see this example:
static void Main(string[] args)
{
math m = new math();
m.cc();
m.dd();
}
class math
{
private int x = 100;
public int pp(out int disX)
{
int x = 200;
disX = this.x;
return x;
}
public void cc()
{
int x = 50;
Console.WriteLine(x); //answer: 50
Console.WriteLine(this.x); //answer: 100
}
public void dd()
{
int t;
Console.WriteLine(pp(out t)); // answer: 200
Console.WriteLine(t); //answer: 100
}
}