What is a better way? Downcasting? Interface? Abstract class?

1.2k views Asked by At

All,

I have to be doing this wrong. It seemed like a good idea at the time but as I get deeper into it, I think there is a more proper programmatic way of going about it. Thus I ask you...

One note. I'm using Google AppEngine and the Datastore to store this information.

Ok... lets say I have a Super Class of Vehicle, which then has 3 Sub-Classes... Car, Truck, Motorcycle.

In the Super Class, there are 3 properties... Manufacturer, Model, Type

For example, these might be:

  • Manufacturer: Ford
  • Model: Focus
  • Type: Car

So in the Datastore, I have numerous Vehicle entities with these properties. So if the user wants to see all the cars... I pull everyhing with a "Car" type.

If the user then wants to add one of these Vehicles to a "favorites" list, I then convert the Vehicle object into its specific Sub-Class based upon what type it is. This then adds the extra properties of that specific Sub-Class.

This new child entity is store in the Datastore with its added properties.

So basically, I'm downcasting, for example, from a Vehicle to a Car. I have done this by creating an extra constuctor in the Car class that takes Vehicle as an argument. Once created, the Car object now has all the properties (Manufacturer, Model, Type) set, and all the new properties that come with its specific implementation.

This just seems convoluted and wrong. It works but there has got to be a better way of doing this.

The main reason I chose this way is because of the way the GAE Datastore works. Its "cheaper" to store the Super Class and its limited properties and query those. Long story.

I'm trying to wrap my head around using Interfaces and/or Abstract classes for this but I wanted to get all of your input.

Thanks for the help.

2

There are 2 answers

0
arcy On BEST ANSWER

I don't think you want a super/sub class structure here. Your problem as described has you "changing" an object from one type to another, and you cannot change the type of a Java object. You can create a new object, but then you have to move all your information from one to another, and maintenance becomes a problem.

I suggest that you have a class that represents your vehicle, and that it contain a reference to type-specific information; the classes representing each specific type can all extend something, and probably should so that methods within vehicle trying to do something with the type can call a common method to do it regardless of type. But this way, once you decide the specific type, you can add it to an existing vehicle object instead of "changing" it.

You could also explore whether an enumerated type would serve your purpose for type-specific data -- enum types can take constructors, have additional methods, etc. - the Oracle/Java tutorial on enums covers that pretty well.

0
jprusakova On

The type of vehicle is encoded twice: once as an object type, and once as a property. Get rid of one of these, so that there is not a possibility of having a Truck (object type) with property value set to Car. Keep your object structure, or property pointing out the kind of vehicle (I recommend using an Enum), but not both.

To downcast, you do not need to create a new object of the child type. Just downcast:

Car myCar = (vehicle instanceof Car ? (Car)vehicle : null);