为什么抽象 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
被广泛用于定位对象,使 A
的 equals
方法抽象迫使你在 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
(因为 equals
和 hashCode
的合同要求 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 方法抽象化将使您能够做到这一点。
我使用一个库,其中抽象 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
被广泛用于定位对象,使 A
的 equals
方法抽象迫使你在 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
(因为 equals
和 hashCode
的合同要求 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 方法抽象化将使您能够做到这一点。