问题
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