关于平等的最佳做法:过载还是不过载? [英] Best practices regarding equals: to overload or not to overload?

查看:120
本文介绍了关于平等的最佳做法:过载还是不过载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码段:

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"
    }
}

请注意包含返回 false !!!我们似乎丢失了我们的东西!!

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

当然,这个错误是我们意外地重载,而不是重写 的Object.Equals(对象) 。如果我们编写类Thing 而不是如下,则包含返回 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);
            }
        }

有效的Java第2版,第36项:始终使用覆盖注释,使用基本相同的参数来建议应始终如一地使用 @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.

然而,本书没有具体涵盖的是重载是否等于开头是一个好主意。基本上,有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:


  • 仅重载,无覆盖 - 几乎完全错误


    • 这实际上是上面的第一个片段


    • 这实际上是上面的第二个片段

    第3种情况由以下代码段说明:

    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.

    所以问题是:


    • 仅覆盖vs重载和覆盖组合的优缺点是什么?

    • 是否有理由重载等于,或者这几乎肯定是一种不好的做法?

    • 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.

    所以我说不要这样做。

    这篇关于关于平等的最佳做法:过载还是不过载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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