tags:

views:

82

answers:

1

I'm trying to enforce an inheritor of an abstract class to initialize one of the fields in the base.

I can't do this via a constructor in the base because the type of the field requires a reference back to the object creating it. (I suppose I could provide a parameterless ctor for the field type. But I feel that would just be shifting the problem, and it should be immutable anyway).

Perhaps someone can suggest how to do it, or maybe make it so I don't need to do it at all?

This is pretty much what I'm doing:

public abstract class Base
{
    // Would like to force setting in CTOR
    protected BaseImplementation _implementation;  
    protected BaseImplementation Implementation 
    { get { return _implementation; } }

    public void DoSomething()
    {    
        Implementation.DoSomething();
    }
}

public abstract class BaseImplementation
{
    public abstract void DoSomething();
}

public class MyObject : Base
{
    // Note its Nested
    public class MyImplementation : BaseImplementation
    {
        private MyObject _myObject;

        public MyImplementation(MyObject myObject)
        {
            this._myObject = myObject;
        }

        public override void DoSomething()
        {
            // Does something
        }
        public virtual void SomethingElse()
        {
            // Does something else 
        }
    }

    new public MyImplementation Implementation
    {
        get { return (MyImplementation) _implementation; }
    }

    public void SomethingElse()
    {
        Implementation.SomethingElse();
    }
}

To give a little context, I have a number of classes which inherit from the base. They, intern have multiple ways which they can manipulate their state. This has been the best solution I have come up with for handling that.

Edit

I forgot to mention that I'm not using an Abstract property because it means I cant use new public MyImplementation Implementation {.... I don't want to have to cast Implementation to MyImplementation whenever I use functionality specific to the derived class (thus using new in the first place) or create multiple fields containing the same object.

+8  A: 

Don't add a field to the base class. Simply make it an abstract property. Derived classes will have to override it and return their own value.

protected abstract BaseImplementation Implementation { get; }

Alternatively, you can make the base class constructor accept an argument of type BaseImplementation and have the derived class initialize it:

public abstract class Base { 
    protected Base(BaseImplementation implementation) {
        _implementation = implementation; 
    }

    private BaseImplementation _implementation;  
    protected BaseImplementation Implementation { get { return _implementation; } }
}

public class Derived : Base {
    public Derived() : base(new MyImplementation()) { }
    // ...
}
Mehrdad Afshari
+1. ah, that's much better!
Mitch Wheat
+1. I would also consider using an interface (e.g. IImplementation) instead of an abstract class, it will give you greater freedom to implement it in different ways.
Groo
Please see my edit as to why I'm not doing this already.
Courtney de Lautour
@Courtney: You are sacrificing design correctness for syntactic beauty, which is not a good thing IMO. This is not a big deal. Simply declare a new property with a different name in the derived class: `public MyImplementation MyImplementation`.
Mehrdad Afshari
@Courtney: The alternative method might suit your case better.
Mehrdad Afshari
Alas ': base(new MyImplementation())' isn't valid when MyImplementation requires a reference to the object creating it ('this' isn't available). However I figured in bed I can create an abstract property called DefaultImplementation, and use that from the Base CTOR to set the field.
Courtney de Lautour
`this` is unavailable in that context, of course, but you can call static methods and decide the output based on the arguments passed to the constructor. That's enough most of the time.
Mehrdad Afshari