J. Блох в своей эффективной Java предоставляет несколько правил реализации для метода equals. Вот они:
• Возвратный: Для любого ненулевого опорного значения х, x.equals(х) должны return true.
• Симметричный: для любых непустых опорных значений x и y, x.equals(y) должен возвращать true тогда и только тогда, когда y.equals(x) возвращает true.
• Transitive: для любых непустых опорных значений x, y, z, если x.equals(y) возвращает true, а y.equals(z) возвращает true, тогда x.equals(z) должно возвращать true.
• Согласовано: для любой ненулевой ссылки значения x и y, множественные вызовы x.equals(y) последовательно возвращает true или последовательно возвращает false, если не используется информация в равных сопоставлениях по объектам изменяется.
• Для любого непустого опорное значение х, x.equals(нуль) должен возвращать ложь.
Но позже в книге он упомянул так называемый принцип подписи Лискова:
Принцип подстановки Лискова гласит, что любое важное свойство тип должен также содержать для своих подтипов, так что любой написанный метод для типа должны работать одинаково хорошо по своим подтипам
Я не вижу, как это связано с контрактами equals
. Должны ли мы на самом деле придерживаться этого при написании эквивалентной реализации?
Вопрос о реализации метода для подклассов. Вот пример из книги:
private static final Set<Point> unitCircle;
static {
unitCircle = new HashSet<Point>();
unitCircle.add(new Point(1, 0));
unitCircle.add(new Point(0, 1));
unitCircle.add(new Point(-1, 0));
unitCircle.add(new Point(0, -1));
}
public static boolean onUnitCircle(Point p) {
return unitCircle.contains(p);
}
public class CounterPoint extends Point {
private static final AtomicInteger counter = new AtomicInteger();
public CounterPoint(int x, int y) {
super(x, y);
counter.incrementAndGet();
}
public int numberCreated() { return counter.get(); }
}
и следующую реализацию:
// Broken - violates Liskov substitution principle (page 40)
@Override public boolean equals(Object o) {
if (o == null || o.getClass() != getClass())
return false;
Point p = (Point) o;
return p.x == x && p.y == y;
}
Хорошо, нарушает и что тогда? Я не понимаю.