c# - 为什么在具体装饰器的构造函数中我必须重复超类构造函数的代码?
问题描述
试图实现装饰器模式——在这个例子中为了简单起见,我们只有 1 个名为 ConcreteDecorator1 的具体装饰器,我让它工作,这个例子是功能性的。但是我的问题是围绕 OOP 的,更具体地说,我不明白为什么在 ConcreteDecorator1 的这一行上出现“组件为空”异常:myField = this.myField + component.Operation();
在添加this.component = component
同一个类的构造函数之前?我的意思是this.component = component
发生在超类(装饰器)的 c-tor 中,那为什么还不够呢?
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;
}
}
所以底线:为什么在具体装饰器的构造函数中我必须重复超类构造函数的代码?我想我可以这样:
public ConcreteDecorator1(Component component) : base(component)
{
}
如果需要,可能会在正文中添加一些额外的东西,比如额外的逻辑(这里不需要,只是说)。
稍后编辑 - 另一个工作变体(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;
}
}
仍然不是很好,因为我宁愿在装饰器中定义操作,在具体装饰器中我只会设置 myField 值......
变体 3(稍后更新,也有效):
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();
}
}
解决方案
您不必重新定义公共对象private Component component;
。改变组件的双重定义如下
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;
}
}
使用此代码,您只设置父类的组件,而不是此类的组件。并且当执行这段代码时myField = this.myField + component.Operation ();
,程序给出了一个空错误。
public ConcreteDecorator1(Component component) : base(component)
{
//This is wrong because the component is never set
}
假设您有两个名为 x 的变量。您在一个函数中全局定义一个,另一个在本地定义。当您想要访问全局变量时,您必须使用此关键字。
看这个例子:
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
}
}
推荐阅读
- java - 使用 SAX 解析器访问节点内的节点
- c++ - cmake/make (OBJECT) 依赖问题——当标头改变时不重建
- php - 功能 - 删除 3 个 lasts 元素
- terminal - 什么,如果有的话,ansi 控制序列重新着色已经打印的文本?
- python-3.x - Module not found error even though I have pip installed the module
- vue.js - VueJS:在没有集中存储(vuex 或 eventBus)的情况下直接访问子项(使用 vue-router)时访问子项中的父道具
- php - 如何从数组中获取值?
- azure-api-apps - 如何在 AZURE 中托管之前测试我的 API 应用程序
- sql - Add-Type 在首次运行 PowerShell 脚本时不起作用
- sql - 使用 SQL UNPIVOT 使用多列使行垂直