I have a four domain objects in my project. They have 3 common attributes namely id, name and age.
public class Domain1 {
private String id;
private String name;
private int age;
...
}
public class Domain2 {
private String id;
private String name;
private int age;
...
}
public class Domain3 {
private String id;
private String name;
private int age;
...
}
public class Domain4 {
private String id;
private String name;
private int age;
...
}
Domain1 and Domain4 comparison is only based on 'id' attribute when compared with other domains (Domain2, Domain3 and Domain4) or with each other. Domain2 and Domain3 comparison is based on id, name and age except when compared to each other.
For ex,
Domain1 equal Domain2 - equality based on id
Domain1 equal Domain3 - equality based on id
Domain1 equal Domain4 - equality based on id
Domain2 equal Domain3 - equality based on id, name and attribute
Domain2 equal Domain4 - equality based on id
Domain3 equal Domain4 - equality based on id
so on...
How can implement such a equality requirement?
-
3I would generally say that making an instance of one type equal to an instance of another type is a bad idea. I can't remember ever seeing that implemented correctly and usefully.Jon Skeet– Jon Skeet2015年10月20日 16:37:30 +00:00Commented Oct 20, 2015 at 16:37
3 Answers 3
I would just try not to do this. The rules you've suggested violate the requirements of Object.equals
, in particular:
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
Now consider your rules with:
Domain1 d1 = new Domain1("id1", "name1", "attribute1");
Domain2 d2 = new Domain2("id1", "name1", "attribute1");
Domain3 d3 = new Domain3("id1", "name3", "attribute3");
Now d2.equals(d1)
is true (they match on ID) and d1.equals(d3)
is true (they match on ID) but d2.equals(d3)
is false, because they don't match on attribute and name.
I don't think I remember ever seeing equality across entirely disparate types working out nicely. It's hard enough trying to avoid surprises in a superclass/subclass relationship, but this is worse.
9 Comments
You can just override
the equals()
method for those four domain objects according to your requirements.
You can generate it through your IDE and modify it to fit your requirements.
Edit: In your method you can look for the type of the object that you are comparing to:
public boolean equals(Object object){
if(object instancof Domain4) //Specific implementation
....
}
However, like Jon said it would violate the requirements of Object.equals.
3 Comments
isEqualTo()
for exampleMaybe I'm not understanding the use case here, but you could try using a Comparator and then create a ComparableDomain interface that has something like getType (this returns Domain1, Domain2, etc) as well as the common getters/setters (for name, age, and id) and you make all your Domains implement the ComparableDomain.
Now you can compare two different Domain objects by first asking their type and then proceeding to check the fields as you described.
public class DomainComparator implements Comparator<ComparableDomain>{
@Override
public int compare(ComparableDomain domain1, ComparableDomain domain2) {
//First check domain1 and domain2 are actually ComparableDomain objects
if(domain1.getType().equals("Domain1") && domain2.getType().equals("Domain2")){
// Do comparison between d1 and d2
}
...
elseif(domain1.getType().equals("Domain2") && domain2.getType().equals("Domain3"){
// Do comparison based on id, name and attribute
}
}
}
This might not be very elegant but it seems like it could solve the issue. Or maybe I just misunderstood the problem. I know Comparators are usually used for sorting and such, but in this case it might work.