Java - 基类和子类中的equals方法 [英] Java - equals method in base class and in subclasses

查看:506
本文介绍了Java - 基类和子类中的equals方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的基类,后来由许多单独的类扩展,这可能会引入新的字段,但不一定。我在基类中定义了一个equals方法,但是也为一些子类重写了它。可以在基础/子类中混合定义吗?在我的例子中,它是为了避免代码重复检查相同的字段。

I have a simple base class, which is later extended by many separate classes, which potentially introduce new fields, but not necessarily. I defined an equals method in the base class, but also overriden that for a few subclasses. Is it OK to mix definitions in base/subclasses? In my case it was to avoid code duplication checking the same fields.

推荐答案

看看实施等于()允许来自Angelika Langer的混合类型比较。

Take a look at "Implementing equals() To Allow Mixed-Type Comparison" from Angelika Langer .

以下是一些问题和可能的解决方案的简要说明:

Here is a brief explanation of some problems and a possible solution:

等于合同说(其中包括):

The equals contract says (amongst others):


它是对称的:对于任何非空引用值x和y,当且仅当y时,x.equals(y)应该返回true。 equals(x)返回true。

It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.

这意味着如果您的子类引入新字段并且您正在比较基类的对象(或不覆盖等于的另一个子类)到该子类的对象。

That means you might get problems if your sub class is introducing new fields and you're comparing an object of the base class (or another sub class that doesn't override equals) to an object of this sub class.

不要执行以下操作: / strong>

Do NOT do the following:

class BaseClass {
    private int field1 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BaseClass) {
            return field1 == ((BaseClass) obj).field1;
        }
        return false;
    }
}

class BadSubClass extends BaseClass {
    private int field2 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof BadSubClass) {
            return super.equals(obj) 
                    && field2 == ((BadSubClass) obj).field2;
        }
        return false;
    }
}

因为你得到了

BaseClass baseClass = new BaseClass();
BadSubClass subClass = new BadSubClass();

System.out.println(baseClass.equals(subClass)); // prints 'true'
System.out.println(subClass.equals(baseClass)); // prints 'false'

可能的解决方案:

用类比较替换 instanceof -check:

Replace the instanceof-check with a class comparison:

obj != null && obj.getClass() == getClass()

使用此解决方案的对象 BaseClass 永远不会等于任何子类的对象。

With this solution an object of BaseClass will never be equal to an object of any subclass.

如果你创建另一个 SubClass 没有 @Override 等于方法,两个 SubClass -objects可以相互等于(如果 BaseClass.equals 检查决定如此)开箱即用,但是 SubClass -object永远不会等于 BaseClass -object。

If you create another SubClass without an @Override of the equals method, two SubClass-objects can be equal to each other (if the BaseClass.equals check decides so) out of the box, but a SubClass-object will never be equal to a BaseClass-object.

一个好的实现可能是如下:

A good implementation could be as follows:

class BaseClass {
    private int field1 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj.getClass() == getClass()) {
            return field1 == ((BaseClass) obj).field1;
        }
        return false;
    }
}

class GoodSubClass extends BaseClass {
    private int field2 = 0;

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof GoodSubClass) {
            return super.equals(obj) && field2 == ((GoodSubClass) obj).field2;
        }
        return false;
    }
}

请参阅上面提到的文章以了解更多高级问题和他们的解决方案。

Please refer to the article mentioned above for more advanced problems and their solutions.

这篇关于Java - 基类和子类中的equals方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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