I have a Location type:
public abstract class Location implements Locatable {
private int x, y;
protected final void setX(int x) {
this.x = x;
}
protected final void setY(int y) {
this.y = y;
}
public final int getX() {
return x;
}
public final int getY() {
return y;
}
}
interface Locatable {
int getX();
int getY();
}
Location
has protected mutator methods, to ensure I can provide an MutableLocation
type, but I'm not sure if this violates the Interface Seggregation principle when creating an ImmutableLocation
.
I feel it doesn't, since the client will never have access to the setters through ImmutableLocation
(cannot call it from an instance, cannot call it from a subclass of ImmutableLocation
). So this was my attempt at a SOLID location type, which I plan on using in a project.
class ImmutableLocation extends Location {
//...
}
class MutableLocation extends Location {
public void adjustX(int amount, IncremeantOperation op) {
int x = op.adjust(x, amount);
setX(x);
}
public void adjustY(int amount, IncremeantOperation op) {
int y = op.adjust(getY(), amount);
setY(y);
}
}
enum IncremeantOperation {
INCREASE {
public int adjust(int target, int amount) {
return target + amount;
}
},
DECREASE {
public int adjust(int target, int amount) {
return target - amount;
}
};
public int adjust(int target, int amount) {
throw new UnsupportedOperationException("Cannot call adjust(int, int) on unknown operation");
}
}
Please give your thoughts. My main concerns are:
- I'm not sure if the enum is an overkill
- If the setters are a violation of SOLID; I'm not sure how else I should do it.
- If
UnsupportedOperationException
is best fit for the adjust method
interface Locatable {
Location getLocation();
}
public abstract class Location {
//may add fields, which explains the class
public abstract int getX();
public abstract int getY();
}
public final class ImmutableLocation extends Location {
private int x, y;
public ImmutableLocation(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
public final class MutableLocation extends Location {
private int x, y;
public MutableLocation(int x, int y) {
this.x = x;
this.y = y;
}
public void adjustX(int x) {
//adjust x
}
public void adjustY(int y) {
//adjust y
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Locatable
would be implemented by anything with a location, such as Entity
:
abstract class Entity implements Locatable {
private Location location;
public Location getLocation() {
return location;
}
}