为什么在具体装饰器的构造函数中我必须重复超类构造函数的代码?

Why in the concrete decorator's constructor I have to repeat code of the superclass constructor?

正在尝试实现装饰器模式 - 为了简单起见,在这个例子中我们只有 1 个名为 ConcreteDecorator1 的具体装饰器,我让它工作,这个例子是功能性的。但是我的问题是关于 OOP 的,更具体地说,我不明白为什么我在 ConcreteDecorator1 的这一行上得到一个“组件为空”的异常:myField = this.myField + component.Operation(); 在相同的构造函数中添加 this.component = component 之前class? 我的意思是 this.component = component 发生在超级 class(装饰器)的 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;
    }
}

所以底线:为什么在具体装饰器的构造函数中我必须重复 superclass 构造函数的代码?我以为我可以这样保留它:

public ConcreteDecorator1(Component component) : base(component)
{
}

并可能在正文中添加一些额外的东西,比如额外的逻辑,如果需要的话(这里不需要,只是说)。

稍后编辑 - 另一个工作变体(变体 2):

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;。修改component的double定义如下

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

使用此代码,您只需设置父 class 的组件,而不是此 class 的组件。而这段代码执行时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
        }
    }