爪哇 - equals方法在基类,并在子类中(Java - equals method in ba

2019-06-18 17:58发布

我有一个简单的基类,这将在后面由许多独立的类,它们潜在地引入新的字段,但不一定延长。 我所定义的equals方法在基类,也重写,对于几个亚类。 是否可以将混合在基地/子类的定义? 在我的情况下,它是为了避免代码重复检查相同的字段。

Answer 1:

在看看“实现equals()方法来分析混合类型比较”从安格兰格。

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

equal的说,(其中包括):

对称性:对于任何非空的参考值x和y,x.equals(y)的应返回true,当且仅当y.equals(x)返回真。

这意味着,如果你的子类是引入新的领域,你的基类(或没有重载equals另一个子类)的对象与该子类的对象,你可能会得到的问题。

不要做以下操作:

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:

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

通过此解决方案的一个目的BaseClass永远不会等于任何亚类的一个对象。

如果创建另一个SubClass没有@Override了的equals方法中,两个SubClass -objects可以彼此相等(如果BaseClass.equals检查决定的话)的开箱,而是一个SubClass -object永远不会等于BaseClass -object。

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

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

请参阅更先进的问题及其解决方案上面提到的文章。



Answer 2:

不,这不是可能引入新的领域,其相关的equals方法时,以符合平等的合同。 请参阅“有效的Java”由Joshua布洛赫以获取更多信息。

编辑:

我没有书在手的权利,但我认为这是确定的,如果基类是抽象/不能被实例化。



Answer 3:

我认为这是完全正常的,只要你按照eqauls()和hashCode()方法的合同。



Answer 4:

您可以使用super()方法来调用你扩展,以防止任何需要重复的代码之类的方法

public class BaseClass {
  public boolean equals(BaseClass other) {
    return (other.getBlahblah() == this.Blahblah && .....);
  }
}

public class DerivedClass extends BaseClass {
  public boolean equals(DerivedClass other) {
    return (super(other) && other.getNewAttribute() == this.NewAttribute.....);
  }
}


Answer 5:

相当有效的方法。 问题是你的一个子类如由其父束缚,但必须保持平等的定义。 否则,你的破等于功能,在运行时,这可能会导致一些非常独特的场景。



Answer 6:

我想,这是完美的,提供equals(Object obj)hashCode()中的方法实现super classJava那样。 我们都知道的Java提供hashCode() and equals(Object obj)的基类方法实现java.lang.Object继承和不断需要时,我们override我们对它们class



Answer 7:

虽然下面不处理任何情况下,我发现它是相当实用的。 我用过很多次,当我有两个超类和比赛中的一个子类。 我不想间对它们进行比较,但我也不想重新实现所有超类的()为子类等于。 它处理:

  • a.equals(B)== b.equals(a)中
  • 不重复场比较代码
  • 容易推广的任何子类深度
  • Subclass.equals(超类)==假
  • Superclass.equals(子类)==假

代码示例

// implement both strict and asymmetric equality
class SuperClass {
   public int f1;
   public boolean looseEquals(Object o) {
      if (!(o instanceof SuperClass)) return false;
      SuperClass other = (SuperClass)o;
      return f1 == other.f1;
   }
   @Override public boolean equals(Object o) {
      return looseEquals(o) && this.getClass() == o.getClass();
   }
}
class SubClass extends SuperClass {
   public int f2;
   @Override public boolean looseEquals(Object o) {
      if (!super.looseEquals(o)) return false;
      if (!(o instanceof SubClass)) return false;
      SubClass other = (SubClass)o;
      return f2 == other.f2;
   }
   // no need to override equals()
}


文章来源: Java - equals method in base class and in subclasses
标签: java equals