重载是否值得 [英] Is overloading equals worthwhile

查看:60
本文介绍了重载是否值得的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下片段:

import java.util.*;
public class EqualsOverload {
    public static void main(String[] args) {
        class Thing {
            final int x;
            Thing(int x)          { this.x = x; }
            public int hashCode() { return x; }

            public boolean equals(Thing other) { return this.x == other.x; }
        }
        List<Thing> myThings = Arrays.asList(new Thing(42));
        System.out.println(myThings.contains(new Thing(42))); // prints "false"
    }
}

注意contains返回false!!!我们好像丢了东西!!

Note that contains returns false!!! We seems to have lost our things!!

当然,错误在于我们不小心重载,而不是覆盖Object.equals(Object).如果我们将 class Thing 写成如下,那么 contains 会按预期返回 true.

The bug, of course, is the fact that we've accidentally overloaded, instead of overridden, Object.equals(Object). If we had written class Thing as follows instead, then contains returns true as expected.

        class Thing {
            final int x;
            Thing(int x)          { this.x = x; }
            public int hashCode() { return x; }

            @Override public boolean equals(Object o) {
                return (o instanceof Thing) && (this.x == ((Thing) o).x);
            }
        }

Effective Java 2nd Edition,Item 36:Consistently use the Override annotation,使用本质上相同的论点来建议应该一致地使用 @Override.这个建议当然很好,因为如果我们试图在第一个片段中声明 @Override equals(Thing other),我们友好的小编译器会立即指出我们的愚蠢的小错误,因为它是一个重载,而不是覆盖.

Effective Java 2nd Edition, Item 36: Consistently use the Override annotation, uses essentially the same argument to recommend that @Override should be used consistently. This advice is good, of course, for if we had tried to declare @Override equals(Thing other) in the first snippet, our friendly little compiler would immediately point out our silly little mistake, since it's an overload, not an override.

然而,本书没有具体介绍的是重载 equals 是否是一个好主意.基本上,有 3 种情况:

What the book doesn't specifically cover, however, is whether overloading equals is a good idea to begin with. Essentially, there are 3 situations:

  • 仅过载,无覆盖 -- 几乎肯定是错误的
    • 这基本上是上面的第一个片段
    • 这基本上是上面的第二个片段

    下面的代码片段说明了第三种情况:

    The 3rd situation is illustrated by the following snippet:

            class Thing {
                final int x;
                Thing(int x)          { this.x = x; }
                public int hashCode() { return x; }
    
                public boolean equals(Thing other) { return this.x == other.x; }
                @Override public boolean equals(Object o) {
                    return (o instanceof Thing) && (this.equals((Thing) o));
                }
            }
    

    这里,即使我们现在有 2 个 equals 方法,仍然有一个相等逻辑,它位于重载中.@Override 只是委托给重载.

    Here, even though we now have 2 equals method, there is still one equality logic, and it's located in the overload. The @Override simply delegates to the overload.

    所以问题是:

    • 仅覆盖"与过载和覆盖组合"的优缺点是什么?
    • 重载 equals 是否有理由,或者这几乎肯定是一种不好的做法?
    • What are the pros and cons of "override only" vs "overload & override combo"?
    • Is there a justification for overloading equals, or is this almost certainly a bad practice?

    推荐答案

    我不认为重载 equals 的情况,除了它更容易出错且更难维护,尤其是在使用继承时.

    I'dont see the case for overloading equals, except that is more error-prone and harder to maintain, especially when using inheritance.

    在这里,保持自反性、对称性和传递性或检测它们的不一致可能非常困难,因为您必须始终了解被调用的实际 equals 方法.想想一个大的继承层次结构,只有一些类型实现了自己的重载方法.

    Here, it can be extremly hard to maintain reflexivity, symmetry and transitivity or to detect their inconsistencies, because you always must be aware of the actual equals method that gets invoked. Just think of a large inheritance hierarchie and only some of the types implementing their own overloading method.

    所以我会说不要这样做.

    So I'd say just don't do it.

    这篇关于重载是否值得的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆