C# Design – Applying Composition Over Inheritance to Vehicle Classes

ccompositiondesigninheritance

I have a car maintenance garage program that has an abstract Vehicle class that has several derived classes like Car MotorCycle, etc. Each of those derived vehicles in turn is either a fuel or an electric vehicle. So instead of having a FuelCar, ElectricCar, FuelMotorCycle, ElectricMotorCycle etc, I'm trying to implement it using composition.

The problem now is that I would have to check all the time if it's an electric or fuel vehicle, and then do as cast (that's like reinterpret_cast from c++) accordingly, or would have to wrap each as cast with try catch. It adds complexity to the code.

Another option was removing the EnergySource empty class and have each vehicle to hold both Fuel and Electric and to initialize only one in the ctor, but it doesn't seem right to have a fuel car that also have an electric part (even if that part is null). Although this seems the simplest of the three.

Any suggestions on what is the best approach?

Here's the UML diagram of what I currently have:

enter image description here

Code: http://pastebin.com/Rt5HccHC

Best Answer

@radarbob those members are specified, I didn't choose them.

My sympathies.


... Hybrid cars shouldn't be allowed and are irrelevant.

Ok. Then you'd better not have both a Fuel and Electric properties in Vehicle. It "sends the wrong message."


... I don't see how placing properties in interfaces help here, I'm still in square one.

Throughout the StackExchange universe I see the way over-use of interfaces (the keyword kind). I think it is an exuberant mis-application and mis-understanding of "code to interfaces not implementation."


... Lastly, you mean a solid rhombus en.wikipedia.org/wiki/Class_diagram#Relationships

Jessica Simpson on UML


... Anything else you would like to add?

Yes.

Wrap a Vehicle in a VehicleEnergy class

Given the design as shown, pass a Vehicle instance into a VehicleEnergy class with appropriate wrapper methods, or properties, to query the vehicle-EnergySource kind that it is. But I don't see how you can get around the fact that somewhere, somehow you have to interrogate the object.

This feels like a good separation of concerns compromise. I wonder if the flurry of comments on this thread is the result of - a symptom of - conflicting concerns.

I think this hybrid design (pun intended) expresses the separate aspects and then expresses their interaction in a coherent interface (the non-keyword kind).

The Vehicle object can always be used as-is, or disguise itself, so to speak.

Oh, yes... I might use the factory pattern and pass in an enum for the vehicle-enery desired. There will be no enum member for a hybrid vehicle so this becomes a strongly typed way of communicating that "hybrid" is undefined.

Related Topic