Reputation: 155
I have two very simple classes. Both have 2 variables which are UUIDs, and I'm thinking about what the best approach is for extracting it into a common class.
Below are the classes I have defined:
@AllArgsConstructor
final class ObjectKey
{
@Getter
private UUID sourceId;
@Getter
private UUID targetId;
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
ObjectKey key = (ObjectKey) o;
return sourceId.equals(key.getSourceId()) && targetId.equals(key.getTargetId());
}
@Override
public int hashCode()
{
return (sourceId.hashCode() + targetId.hashCode()) * 31;
}
}
final class AnimalKey
{
@Getter
private UUID catId;
@Getter
private UUID dogId;
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o == null || getClass() != o.getClass())
{
return false;
}
AnimalKey key = (AnimalKey) o;
return dogId.equals(key.getDogId()) && catId.equals(key.getCatId());
}
@Override
public int hashCode()
{
return (catId.hashCode() + dogId.hashCode()) * 31;
}
}
So I'm wondering what is the best practice, since both classes basically have the same number of variables with the same type... only that the variable names are different.
Of course one option is to have only 1 class that has generic names like firstID
and secondID
. But then the code using the getters/setters for these classes are not very easy to read and understand. Is there any obvious approach I'm missing?
Upvotes: 1
Views: 74
Reputation: 886
I don't think there is anything as elegant as you are envisaging or not much of a necessity/benefit. However, a couple of options that come to mind are to have a common base class and some explicit getters that map to friendlier names and/or and object for a TupleUUID.
@AllArgsConstructor
final class TupleUUID
{
@Getter
private UUID primaryId;
@Getter
private UUID secondaryId;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TupleUUID that = (TupleUUID) o;
return Objects.equals(primaryId, that.primaryId)
&& Objects.equals(secondaryId, that.secondaryId);
}
@Override
public int hashCode() {
return Objects.hash(primaryId, secondaryId);
}
}
@AllArgsConstructor
class TupleKey {
@Getter(AccessLevel.PROTECTED)
private TupleUUID uuid;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
TupleKey that = (TupleKey ) o;
return Objects.equals(key, that.key);
}
@Override
public int hashCode() {
return uuid.hashCode();
}
}
@AllArgsConstructor
final class ObjectKey extends TupleKey {
public UUID getSourceId() {
return getUuid().getPrimaryId();
}
public UUID getTargetId() {
return getUuid().getSecondaryId();
}
}
@AllArgsConstructor
final class AnimalKey extends TupleKey {
public UUID getCatId() {
return getUuid().getPrimaryId();
}
public UUID getDogId() {
return getUuid().getSecondaryId();
}
}
Of course, you can mix and match this and get rid of the TupleKey base class or roll TupleUUID into TupleKey instead.
The benefits of this are questionable unless you are going to have a lot of objects with two unique identifiers.
Upvotes: 2