gpt4 book ai didi

java - 如何覆盖 java 枚举中的(最终)equals 方法?

转载 作者:太空狗 更新时间:2023-10-29 23:02:53 26 4
gpt4 key购买 nike

我在覆盖 Enum 中的 equals 方法以使其与其他类兼容时遇到问题。Enum 实现了一个接口(interface),其想法是可以测试该接口(interface)的所有实现是否相等,无论它们的类型如何。例如:

public interface Group {
public Point[] getCoordinates();
}

public enum BasicGroups implements Group {
a,b,c; // simplified, they actually have constructors
// + fields and methods
}

public class OtherGroup implements Group {
// fields and methods
}

如果 BasicGroupOtherGroup 具有相同的坐标(以任意顺序),则 equals 方法应返回 true。

执行 myOtherGroup.equals(BasicGroup.a) 时没有问题,但由于 Enums 中的 equals 方法是最终的,我无法覆盖它们。

有什么办法可以解决这个问题吗?就像在另一个 BasicGroup 上测试时一样,使用默认的 equals 方法 (引用相等性),在测试其他类时使用我自己的实现。当我执行 BasicGroup.a.equals(myOtherGroup) 时,如何确保 java 不会使用错误的?

最佳答案

不能 @Override一个final方法(§8.4.3.3);这一点很清楚。 enum类型 ( §8.9 ) 在 Java 中被非常特殊地对待,这就是 equals 的原因是final (还有 clonehashCode 等)根本不可能 @Override equals enum 的方法,您也不会真正想要在更典型的使用场景中使用。

但是,纵观全局,您似乎正在尝试遵循Effective Java 2nd Edition,第 34 项:使用接口(interface)模拟可扩展枚举中推荐的模式(有关 enum 的更多信息,请参阅 language guide):

您已经定义了这个 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 .一个空的 LinkedListequals到一个空的ArrayList反之亦然,因为这就是 interface任务。

在您的情况下,您已选择实现一些 Group作为enum .不幸的是,您现在无法实现 equals根据规范,因为它是 final你不能@Override它。但是,由于目标是遵守 Group 输入,你可以使用decorator pattern通过拥有 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,第 15 项:最小化可变性),否则您可能不应该使用 enum 来实现它首先。鉴于此,请考虑Effective Java 2nd Edition,第 25 项:优先使用列表而不是数组。您可以选择 getCoordinates()返回 List<Point>而不是 Point[] .您可以使用 Collections.unmodifiableList (另一个装饰器!),这将使返回的 List不可变的。相比之下,由于数组是可变的,因此在返回 Point[] 时您将被迫执行防御性复制。 .

另见

关于java - 如何覆盖 java 枚举中的(最终)equals 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3564139/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com