Вы можете НЕ @Override
a final
метод ( §8.4.3.3 ); это очень ясно. enum
типы ( §8.9 ) обрабатываются в Java очень специально, поэтому equals
равен final
(также clone
, hashCode
и т. Д.). Просто невозможно @Override
метод equals
для enum
, и вы не захотите этого в более типичном сценарии использования.
ОДНАКО , глядя на общую картину, похоже, что вы пытаетесь следовать шаблону, рекомендованному в Effective Java 2nd Edition, Item 34: Эмуляция расширяемых перечислений с интерфейсами (см. справочник по языку для получения дополнительной информации о enum
):
Вы определили это interface
(теперь задокументировано явно для ожидаемого equals
поведения):
public interface Group implements Group {
public Point[] getCoordinates();
/*
* Compares the specified object with this Group for equality. Returns true
* if and only if the specified object is also a Group with exactly the same
* coordinates
*/
@Override public boolean equals(Object o);
}
Для interface
вполне приемлемо определить, как метод equals
должен вести себя, конечно, для разработчиков. Это в точности так, например, с List.equals
. Пустой LinkedList
равен equals
для пустого ArrayList
и наоборот, потому что это то, что мандат interface
.
В вашем случае вы решили реализовать некоторые Group
как enum
. К сожалению, теперь вы не можете реализовать equals
согласно спецификации, так как это final
и вы не можете @Override
его. Однако, поскольку цель состоит в том, чтобы соответствовать типу Group
, вы можете использовать шаблон декоратора , имея ForwardingGroup
следующим образом:
public class ForwardingGroup implements Group {
final Group delegate;
public ForwardingGroup(Group delegate) { this.delegate = delegate; }
@Override public Point[] getCoordinates() {
return delegate.getCoordinates();
}
@Override public boolean equals(Object o) {
return ....; // insert your equals logic here!
}
}
Теперь вместо того, чтобы использовать enum
константы непосредственно как Group
, вы переносите их в экземпляр ForwardingGroup
. Теперь этот Group
объект будет иметь желаемое поведение equals
, как указано interface
.
То есть вместо:
// before: using enum directly, equals doesn't behave as expected
Group g = BasicGroup.A;
Теперь у вас есть что-то вроде:
// after: using decorated enum constants for proper equals behavior
Group g = new ForwardingGroup(BasicGroup.A);
Дополнительные примечания
Тот факт, что enum BasicGroups implements Group
, даже если он не соответствует спецификации Group.equals
, должен быть очень четко задокументирован . Пользователи должны быть предупреждены, что константы должны быть, например, завернутый в ForwardingGroup
для правильного поведения equals
.
Обратите внимание, что вы можете кэшировать экземпляры ForwardingGroup
, по одному на каждую enum
константу. Это поможет уменьшить количество создаваемых объектов. Согласно Effective Java 2nd Edition, пункт 1: рассмотрите статические фабричные методы вместо конструкторов , вы можете рассмотреть возможность использования ForwardingGroup
определения static getInstance(Group g)
метода вместо конструктора, что позволяет ему возвращать кэшированные экземпляры.
Я предполагаю, что Group
является неизменяемым типом ( Effective Java 2nd Edition, Item 15: Минимизируйте изменчивость ), иначе вы, вероятно, не должны реализовывать его с enum
в первом место. Учитывая это, рассмотрим Effective Java 2nd Edition, пункт 25: Предпочитаю списки массивам . Вы можете выбрать getCoordinates()
вернуть List<Point>
вместо Point[]
. Вы можете использовать Collections.unmodifiableList
(другой декоратор!), Что сделает возвращаемый List
неизменным. В отличие от этого, поскольку массивы являются изменяемыми, вам придется выполнять защитное копирование при возврате Point[]
.
Смотри также