patternjavaMinor
Subclassing or not?
Viewed 0 times
notsubclassingstackoverflow
Problem
I have a class called
For some business reason I need to create an Identifier which I can use to 'identify' Foo instances (having some
Since this
I'm considering two designs as follows -
Subclassing -
```
public abstract class FooIdentifier {
private String optionalProperty;
public enum Type {
NAME_BASED, ID_BASED
}
protected FooIdentifier(String optionalProperty) {
this.optionalProperty = optionalProperty;
}
public String getOptionalProperty() {
return optionalProperty;
}
public abstract Type getType();
}
public class NameBasedIdentifier extends FooIdentifier {
private String name;
public NameBasedIdentifier(String optionalProperty, String name) {
super(optionalProperty);
this.name = name;
}
public NameBasedIdentifier(String name) {
this(null, name);
}
public String getName() {
return name;
}
@Override public Type getType() {
return Type.NAME_BASED;
}
}
public class IdBasedIdentifier extends FooIdentifier {
private long uniqueId;
public IdBasedIdentifier(String optionalProperty, long uniqueId) {
super(optionalProperty);
this.uniqueId = uniqueId;
}
public IdBasedIdentifier(long uniqueId) {
Foo public class Foo {
private String optionalProperty;
private String name;
private long uniqueId;
// getters/setters for above properties
}For some business reason I need to create an Identifier which I can use to 'identify' Foo instances (having some
name/uniqueId) in some business flow. I want to create some FooIdentifier class which will be used to identify Foo instances (this FooIdentifier has other business use cases as well and this is one of the use cases). Since this
FooIdentifier will be either based on name or uniqueId we need to distinguish between those two scenarios, optionalProperty is common in both the scenarios.I'm considering two designs as follows -
Subclassing -
```
public abstract class FooIdentifier {
private String optionalProperty;
public enum Type {
NAME_BASED, ID_BASED
}
protected FooIdentifier(String optionalProperty) {
this.optionalProperty = optionalProperty;
}
public String getOptionalProperty() {
return optionalProperty;
}
public abstract Type getType();
}
public class NameBasedIdentifier extends FooIdentifier {
private String name;
public NameBasedIdentifier(String optionalProperty, String name) {
super(optionalProperty);
this.name = name;
}
public NameBasedIdentifier(String name) {
this(null, name);
}
public String getName() {
return name;
}
@Override public Type getType() {
return Type.NAME_BASED;
}
}
public class IdBasedIdentifier extends FooIdentifier {
private long uniqueId;
public IdBasedIdentifier(String optionalProperty, long uniqueId) {
super(optionalProperty);
this.uniqueId = uniqueId;
}
public IdBasedIdentifier(long uniqueId) {
Solution
Assuming you need to retrieve the string or long values (I don't see getters for them in the single class) I prefer the three classes, with the getter methods also in the base class to avoid a cast. Each derived class would unconditionally throw an exception if the inappropriate getter method is called, whereas a single class needs an if statement in both getters. Same goes for if you added a toString() method, equals(long), equals(string) or other methods to the base class - no if statements for "which type of class am I" that are necessary with a single class.
Context
StackExchange Code Review Q#14687, answer score: 2
Revisions (0)
No revisions yet.