How to create a Class when its attributes are dynamic & variable in Java, C++ or any Object-Oriented Language?-Collection of common programming errors
I would argue that this is a prime example of when you should use inheritance. Take the following for example:
Abstract Class Item
{
// This class will never be instantiated, but it can hold
// things that are common to all Items, such as sale price.
private int price;
public int getPrice() { return price; }
// etc.
}
Class VendorOneItem : Item
{
// This class gets 'price' and 'getPrice' by default,
// since it inherits from Item
private String color;
private String model;
// etc.
}
Class VendorTwoItem : Item
{
// This class also gets 'price' and 'getPrice'
private Double width;
private Double height;
// etc.
}
I know this doesn’t take the route of dynamically reading in the data, but this is the more clear-cut way in my mind. Even if you are somehow able to read in all of the data dynamically, how would be able to process that data? As Reed noted, you could have a Dictionary or a Map of some sort, which is reasonable. You’d have data that might look like:
{"key": value}
{"Color": "blue"}
{"Price": 9.99}
{"Model": 1234-567-890}
or
{"Price": 129.99}
{"Height": 12.750}
{"Width": 8.55}
But then you’re just shifting your problem from figuring out the attributes at compile time to figuring out the attributes at run-time. In order to process these two, some part of your code will have to know what to do with "Width"
and "Height"
, and it will also need to know what to do with "Model"
and "Color"
. Reflection is one possibility, but what’s being described by these items are fundamentally different, and it might be next to impossible to generalize an algorithm that deals with their details.
It seems far easier to me to start with a base class and have inherited classes that know the details. You can even make collections of Item
in your code along the way, without having to know the exact type of each object.
In C++:
std::vector items;
items.push_back(new VendorOneItem());
items.push_back(new VendorTwoItem());
Now say you add this to the Item
class:
virtual public void ProcessItem()=0; //This will throw compilation errors
// if all derived classes don't define ProcessItem
So now, back where the vector items
is defined, you can do this:
items[0].ProcessItem();
items[1].ProcessItem();
And it makes no difference that the two objects are instantiations of different classes. They both must implement ProcessItem, so there’s no problem figuring out which functions to call.