Class base() constructor and pass this

不羁岁月 提交于 2019-12-19 20:43:42

问题


I am trying to implement good design patterns for a program I am writing. I have a class structure like this.

abstract class SomeBase
{
     public SomeObject obj { get; protected set; } 

     protected SomeBase(SomeObject x)
     {
           obj = x;
     }

     //Other methods and fields...
}

public class SomeDerived : SomeBase
{

     public SomeDerived() : base(new SomeObject(this))
     {

     }

}

Now as I;m sure you now, you can't pass this in a contructor because the object hasn't bee initialized. But I was really hoping there was a workaround. It's not best practice for me to allow SomeDerived() to handle the setting of a base classes field. I would like to pass this new object up the chain.

Any ideas?


回答1:


This is not possible, use an Init method after the constructor:

 abstract class SomeBase
 {
      private SomeObject _obj { get; set; } 
      public SomeObject obj 
      {
           get 
           {    // check _obj is inited:
                if (_obj == null) throw new <exception of your choice> ;
                return _obj;
           } 
      }

      protected SomeBase()
      {
           obj = null;
      }

      protected void Init()
      {
           obj = x;
      }

      //Other methods and fields...
 }

 public class SomeDerived : SomeBase
 {

      public SomeDerived() : base()
      {
           Init(new SomeObject(this));
      }

 }



回答2:


Well, you actually have it in the base constructor, so there is no need to pass it.

abstract class SomeBase
{
    public SomeObject obj { get; protected set; }

    protected SomeBase()
    {
        obj = (SomeObject)Activator.CreateInstance(typeof(SomeObject), this); // "this" here is SomeDerived object
    }
}

class SomeDerived : SomeBase
{
    public SomeDerived()
    {
    }
}

class SomeObject
{
    public SomeObject(SomeDerived obj)
    {
        if (obj.obj == null)
        {
            // You have the reference to SomeDerived here
            // But its properties are not yet initialized (both SomeDerived and SomeBase constructors are in the progress of execution)
            // So you should not access them in the SomeObject class constructor
        }
    }
}



回答3:


1) Constructors are WRONG things by it's design at all - it's looks like method of instance, but really it's half-method of half-instance.

2) "Good design programs with patterns" do not cause immediate circular dependency between classes in aggregation as we see here - both classes must know and use each other at creation(!!!) who knows what SomeObject do with "this" in it's constructor???

So in "patterns" where are 2 problems - high dependency between classes and not-usable incapsulation of initialization logic. So we have to find "pattern" way to solve it... hmm.. what to do...

In code u provide i see that derived class just provides it's own logic for property obj u can rewrite it to be auto-initialized propery

public abstract class MyClass{
     private SomeObject _obj ; 
     public SomeObject Obj {get { return  _obj ?? (_obj = InitializeObj() );}} //no setter needed
     protected abstract SomeObject InitializeObj();
}

public class MyRealClass:MyClass {
    protected override SomeObject InitializeObj(){
        return new VerySpecialSomeObject(this, other, another, 1, 2 , false, option: new Options());
    }   
}

For your example such solution provides single "pattern" that win - "polymorphism" )) and gain additional bonus - if "Obj" will not be usefull - it never be created ))))



来源:https://stackoverflow.com/questions/25919007/class-base-constructor-and-pass-this

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!