Reputation: 51
We have a case where we need build a Resource
which can be one of two types: Logical
or Physical
. With each resource subtype, we have a Configuration
attached which can be a LogicalConfiguration
and a PhysicalConfiguration
.
This is done because the configuration objects are editable and need to be versioned. Such as a resource can have two configuration versions: active and draft. A method is provided in Resource
to Add a configuration addConfiguration(Configuration config)
Now, we are facing a issue, LogicalConfiguration
can be wrongly passed to addConfiguration
method for a PhysicalResource
.
Resource resource = new PhysicalResource()
Configuration config = new LogicalResourceConfiguration();
physicalResource.addConfiguration(config)
This invocation will succeed and a wrong configuration will get added. Following ways can be used to avoid this.
instanceOf
check or define a member Type
, but this will kill polymorphism.addLogicalConfiguration
/addPhysicalConfiguration
one of them fails at Runtime.What will be the most suitable way to approach this problem ? Or is there a specific pattern to address these kind of issues?
Upvotes: 0
Views: 59
Reputation: 4843
Put the classes into their own package and make addConfiguration
in Resource
protected.
That way, anyone using your package will discover the error at code writing time.
Upvotes: 0
Reputation: 20163
This structure should fulfill your expectations, by giving a compilation error when an attempting to add an incorrect Configuration
type to a Resource
:
abstract class Configuration {
}
class LogicalConfiguration extends Configuration {
}
class PhysicalConfiguration extends Configuration {
}
abstract class Resource<C extends Configuration> {
private C config;
public void addConfiguration(C config) {
this.config = config;
}
public C getConfig() {
return config;
}
}
class LogicalResource extends Resource<LogicalConfiguration> {
}
class PhysicalResource extends Resource<PhysicalConfiguration> {
}
Use it exactly as you do in your example:
Resource resource = new PhysicalResource()
Configuration config = new LogicalResourceConfiguration();
//COMPILATION ERROR:
physicalResource.addConfiguration(config);
Upvotes: 0
Reputation: 8376
You can add a generic type parameter to the Resource class:
class Resource<T extends Configuration> {
public void addConfiguration(T config) {}
}
Then, you can have:
class PhysicalResource extends Resource<PhysicalConfiguration> {...}
class LogicalResource extends Resource<LogicalConfiguration> {...}
Upvotes: 1