tags:

views:

54

answers:

4

Consider the code in the following example:

abstract class Car
{
    public abstract Engine CarEngine { get; protected set; }

    public Car()
    {
        CarEngine.EngineOverheating += new EventHandler(CarEngine_EngineOverheating);
    }

    void CarEngine_EngineOverheating(object sender, EventArgs e)
    {
        // Subscribing to the event of all engines
    }
}

sealed class Toyota : Car
{
    public Toyota()
    {
        this.CarEngine = new ToyotaEngine();
    }


    public override Engine CarEngine { get; protected set; }
}

abstract class Engine
{
    public event EventHandler EngineOverheating;
}

class ToyotaEngine : Engine
{

}

This code, as expected doesn't work since CarEngine has not yet been initialized. What are my options to resolve such a case?

Several options that I see with their cons:

  1. Subscribe in each child class manually - Results with a lot of boiler plate code and as a result, error-prone.
  2. Initialize() function - Error-prone and redundant.

I'd be happy to see more ideas.

Thanks!

A: 

You can try the example below. This sets the engine on first access.

sealed class Toyota : Car
{
    public Toyota()
    {
    }

    public override Engine CarEngine
    {
        get
        {
            var engine = base.CarEngine;

            if (engine == null)
            {
                engine = new ToyotaEngine();

                base.CarEngine = engine;
            }

            return engine;
        }
    }
}
Pieter
and _how_ does the `Car` constructor know which subclass it's creating, hence which `CarEngine` override it should use?
xtofl
The compiler takes care of that for you. Because you say `new Toyota()`, it automatically uses this overload of `CarEngine`.
Pieter
+2  A: 

can't you pass an Engine object to the ctor of Car which will then set the property (it might be possible to make the setter private then) and register the Event Handler?

Philipp
+5  A: 

Create a constructor in Car taking an engine as a parameter and assign it prior to subscribing to events, like this:

abstract class Car
{
    public abstract Engine CarEngine { get; protected set; }

    public Car(Engine carEngine)
    {
        CarEngine = carEngine;
        CarEngine.EngineOverheating += new EventHandler(CarEngine_EngineOverheating);
    }

    void CarEngine_EngineOverheating(object sender, EventArgs e)
    {
        // Subscribing to the event of all engines 
    }
}

sealed class Toyota : Car
{
    public Toyota()
        : base(new ToyotaEngine())
    {
    }


    public override Engine CarEngine { get; protected set; }
}
Polity
Thanks. I'll go with that :)
VitalyB
A: 

Why don't you tie the Engine to the Car and then register the EventHandler during instantiation of the Engine (if you need an EventHandler with such a design anyway, that is)

Instantiation could look like this

new ToyotaEngine(myToyotaCarInstance).

I think it's perfectly valid for the motor to have a reference to the car.

Falcon
I'd rather have the engine communicate only by events. Child objects that must have a reference to their parent make me jittery :)
VitalyB
I think bidirectional relations are the way to go. Makes life so much easier. In your scenario: Can there be an engine without a car? Or a car, without an engine? Does this kind of lose coupling make sense in your scenario? I doubt it, looks like a suboptimal object model to me!
Falcon