首页 > 解决方案 > 为什么在具体装饰器的构造函数中我必须重复超类构造函数的代码?

问题描述

试图实现装饰器模式——在这个例子中为了简单起见,我们只有 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();
    }
}

标签: c#oopconstructordecoratorsuperclass

解决方案


您不必重新定义公共对象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
        }
    }

推荐阅读