From: Ian R. <ian...@gm...> - 2009-08-29 18:07:54
|
I'm looking into addressing bug 2845939<https://sourceforge.net/tracker/?func=detail&aid=2845939&group_id=239113&atid=1108645>(equals doesn't play well with inheritance). The basic strategy for implementing doEquals(instance, other) in the Pojomator for class Pojoshould be: - if other.getClass() is a proper subclass of Pojo, then invoke other.equals(instance). - Otherwise, verify that other.getClass()is a subclass of the highest class in Pojo's heirarchy which contains all properties which are included in the EQUALS role for Pojo. If so, then do the standard property-by-property equals check. - Otherwise, return false. Taken together, these mean that two instances are equals() to each other iff they share the same set of properties with the EQUALS role, and those proeprties are equal to each other. Note that if a parent class has a method getFoo() which is not in the EQUALS role, and two distinct subclasses add getFoo() to the EQUALS role, these will be seen as distinct properties. Unfortunately, I'm realizing that another sticky issue is the relationship between equals and hashCode. Currently, we have the rule that if an override of a method chosen as a property for a given role (equals, toString or hashCode) is overridden, and the override is also chosen as a property for the same role, then only the parent method will be used. Unfortunately, we do this on a role-by role basis, without paying attention to interactions. This can cause a problem when a method is included in the equals computation in a parent class, and then a child class adds hashCode to it's roles. The result is that an instanceof the parent class might be equals() to an instance of the child class, but the two instances will have different hashCode values. I can see a few different ways of handling this. The easiest is to simply declare that if a method property has role EQUALS and not HASH_CODE, then subclasses can not add the HASH_CODE role to the method. While correct, it is somewhat overrestrictive. If the subclass has also added additional properties, then there is no risk of instances of the parent class being equals()to instances of the child class, so allowing parent properties to take on the additional HASH_CODE role would be fine. Implementing this is a bit more complicated, of course. I might start by doing the easy thing; becoming more permisive in the future allowed. In either case, a question arises of what should happen if someone requests adding a property to a HASH_CODE role where it previously had only the EQUALS role (ignoring the TO_STRING role here). One option is to silently ignore. A second is to log a complaint. A third is to fail fast with a RuntimeException. I lean towards the third - it's almost certainly a programmer error. The only spot of roughness I can see here would be if a project depended on two libraries, with one of the libraries extending a pojomated class of another library. Updates to the library containing the parent class could suddenly cause the child class to be in error, but the error might be tolerable. A RuntimeException approach would make life unpleasant for the project. On the other hand, I suspect this would be an exceedingly rare case. In any event, we can throw an exception today and then become more lenient in the future; going the other direction would not be backwards compatible. - Ian |