微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

试图实现装饰器模式——为了简单起见,在这个例子中,我们只有 1 个名为 ConcreteDecorator1 的具体装饰器,我让它工作了,这个例子是函数式的。然而,我的问题是关于 OOP,更具体地说,我不明白为什么我在 ConcreteDecorator1 的这一行上收到“component is null”异常:myField = this.myField + component.Operation(); BEFORE 添加 this.component = component 在相同的构造函数中班级? 我的意思是 this.component = component 发生在超类 (Decorator) 的 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
        }
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。