为什么抽象 class 可以强制覆盖具体方法?

Why can an abstract class force a concrete method to be overridden?

我使用一个库,其中抽象 class 用抽象方法覆盖从 Object 继承的具体方法:

public abstract class A {
    @Override
    public abstract boolean equals(Object obj);
}

要扩展此 class,我必须实施 equals 方法:

public class B extends A {
    @Override
    public boolean equals(Object obj) {
        return obj != null && obj.getClass() == B.class;
    }
}

为什么抽象方法 (A::equals) 可以覆盖具体方法 (Object::equals)?我看不出这样做的目的。

在这个具体示例中,它非常有意义。如果 A 的子 classes 打算在集合中使用,其中 equals 被广泛用于定位对象,使 Aequals 方法抽象迫使你在 A 的任何子 class 中给出 equals 的非默认实现(而不是使用仅比较实例引用的对象 class 的默认实现)。

当然,您在 B 中建议的 equals 实现毫无意义。您应该比较 2 个 B 实例的属性以确定它们是否相等。

这是一个更合适的实现:

public class B extends A {
    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof B))
            return false;
        B other = (B) obj;
        return this.someProperty.equals(other.someProperty) && this.secondProperty.equals(other.secondProperty);
    }
}

此外,请记住在覆盖 equals 时覆盖 hashCode(因为 equalshashCode 的合同要求 if a.equals(b) == true then a.hashCode() == b.hashCode()).

因为在这种情况下,您可能希望您的对象定义它们自己的 equals,这可能与默认实现的行为不同。

您不应将此视为删除 功能,而应将其视为强制继承对象实现自己的功能。

这将允许您强制子类重新实现一个方法。这是否是个好主意是另一回事。如果您想执行比提供的原始方法更强大的合同,您只会这样做。然后您应该仔细记录新合同。

这意味着你必须实现你自己的equals()方法

因为 Java 中的所有 类 都固有地扩展了 Object class. Class A will inherit the Object#equals method. Suppose you wanted to force a compile error when the equals method is not explicitly implemented like in this example。在没有实现块的情况下使 equals 方法抽象化将使您能够做到这一点。