Click here to Skip to main content
14,981,770 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi there.

I am looking for a good way to implement the following:

I have an Abstract Class Vehicle. Vehicle has several children: Bike, Car, Truck.

All common elements are contained within the parent class which also have a field to indicate the type (a discriminator if you will).

A Car and Truck can tow objects (a bike cannot in this example). These other object need to be available to a Car\Truck but not the Bike.

A Bike, Car and Truck each have fields that are unique to them.

Now by using the Factory Method, you would create do something like this:
C#
Vehicle myVehicle = myVehicleFactory(String typeOfVehicle)


to get a vehicle of the type you need depending on the type you pass along to the factory. Within the factory, any new instances that are created is returned but then cast into a Vehicle class. The problem I have is this: I now cannot access child specific properties\methods by using myVehcile dot whatever... Only the common properties\fields\methods are available.

In other words: I cannot link up the object being towed by a Car or Truck to the myVehicle class. How do I get around this problem (noting that in the future other new vehicle type may be added)

Thanks
Posted
Comments
BobJanova 14-Oct-11 9:30am
   
Why are you using a factory? If you want to make a car, how about new Car(...)?
PJ du Preez 14-Oct-11 9:57am
   
because doing it like that is wrong. I do not want to be limited by concrete classes
BobJanova 14-Oct-11 10:42am
   
If you're going to cast to a specific concrete class, you're still bound to it, just in a more complicated fashion.

If you really don't want to be limited by specific implementations then you need to expose everything you want to do on the interface. As soon as you are making yourself cast, you might as well just declare things of that concrete type (it's more type safe, in fact, because it's compile time and casts can miss).
PJ du Preez 17-Oct-11 2:01am
   
You mean like a strategy pattern?
BillWoodruff 17-Oct-11 6:32am
   
+5 for this interesting question. I have also beat my head against the wall trying to eliminate that required cast for different sub-classed objects of some parent (abstract, or virtual) class created in a Factory pattern implementation.
PJ du Preez 17-Oct-11 6:39am
   
What I managed to do (and I'm working out the kinks at the moment) is to use a combination of the factory method with the strategy pattern. I reckon I'll write a little article on it if it works out.

Make use of the as[^] operator.

C#
Car myCar = myVehicle as Car;
if (myCar != null)
{
    // Call methods specific to Car class.

}
   
Comments
PJ du Preez 14-Oct-11 9:23am
   
That's probably the easiest 5 stars you got ever. I did not know you can do that! Thanks!
André Kraak 14-Oct-11 9:26am
   
Always glad to help and thank for the points :).

You might also want to have a look at the is operator (http://msdn.microsoft.com/en-us/library/scekt9xw%28v=vs.71%29.aspx), which can tell you whether a reference is of a certain type.
PJ du Preez 17-Oct-11 2:59am
   
Sorry dude, I have to reject your solution. I just figure it out and I don't need to use any 'as' or 'is' operators. I'll give an explanation in my solution.
Ha ha. I figured it out!

I simply need to cast mVehicle to a car, bike or truck where i call the factory.

For example:

I have
C#
Vehicle myVehicle = myVehicleFactory(String typeOfVehicle)


if my type is 'bike' then i do this:

C#
Bike myBike = (Bike)myVehicleFactory("bike");


or if it is a truck

C#
Truck myTruck = (Truck)myVehicleFactory("truck");


and this now NOT completely polomorphic but you can kinda use other techniques to determine the concrete type you want to build.
   
Comments
PJ du Preez 17-Oct-11 3:58am
   
Nah, scrap this. there is no difference in the above code and just simple Truck myTruck = new Truck();

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900