package de.skuzzle.polly.tools; /** * <p>Interface which helps to override the {@link Object#equals(Object)} method * according to its specified contract. This interface is based on the article * <a href="http://www.drdobbs.com/jvm/java-qa-how-do-i-correctly-implement-th/184405053"> * How Do I Correctly Implement the equals() Method?</a> by Tal Cohen (May 01, 2002) and * its related <a href="http://tal.forum2.org/equals">discussion page</a>.</p> * * <p>Classes that implement this interfaces, can implement the * equals method using {@link EqualsHelper}:</p> * * <pre> * @Override * public boolean equals(Object obj) { * return EqualsHelper.testEquality(this, obj); * } * </pre> * * This is a sample implementation, which would not allow the implementing class to be * equal to an instance of any of its super classes: * * <pre> * public class Point implements Equatable { * private final x; * private final y; * * // ... * * @Override * public final boolean equals(Object o) { * return EqualsHelper.testEquality(this, obj); * } * * @Override * public Class<?> getEquivalenceClass() { * return Point.class; * } * * @Override * public boolean actualEquals(Equatable o) { * final Point other = (Point) o; * return this.x == other.x && this.y == other.y; * } * } * </pre> * * <p>Now consider the following implementation of a subclass which extends the Point to * carry a new field named 'color'. In this case, instances of ColorPoint can only * be equal to other instances of ColorPoint (as by the return value of * {@link #getEquivalenceClass()}):</p> * * <pre> * public class ColorPoint extends Point { * * private final Color color; * * // ... * * @Override * public Class<?> getEquivalenceClass() { * return ColorPoint.class; * } * * @Override * public boolean actualEquals(Equatable o) { * final ColorPoint other = (ColorPoint) o; * return super.actualEquals(o) && this.color.equals(other.color); * } * } * </pre> * * If instances of ColorPoint shall also be considered equal to a instances of Point, * disregarding the 'color' attribute, no further work would be required. Implementation * of ColorPoint would just look like the following: * * <pre> * public class ColorPoint extends Point { * * private final Color color; * * // ... * } * </pre> * * @author Simon Taddiken * @see EqualsHelper */ public interface Equatable { /** * <p>This method must return a class which is assignment compatible with this one. * That is, it must be either the class of the implementing class itself or any class * which is on a higher level in this class' type hierarchy.</p> * * <p>In short: this method must return a class to which the implementing class can * be casted.</p> * * <p>When testing for equality using * {@link EqualsHelper#testEquality(Equatable, Object)}, two objects o1 and o2 can * only be considered equal, if both implement {@link Equatable} and * <code>o1.getEquivalenceClass().equals(o2.getEquivalenceClass())</code> * </p> * * @return The most specific super class (or this class itself) to which the * implementing class be equal. * @see EqualsHelper */ public Class<?> getEquivalenceClass(); /** * <p>Performs actual test for equality. You may cast the passed object to the type * returned by {@link #getEquivalenceClass()} or any of that types super types.</p> * * <p>After casting, you may perform equality checks for the attributes of your * class.</p> * @param o The object to compare this one with. Note that this is guaranteed to be * <code> != null</code> when called by * {@link EqualsHelper#testEquality(Equatable, Object)} * @return Whether both objects are equal. * @see EqualsHelper */ public boolean actualEquals(Equatable o); }