Ste*_*ler 10 java oop inheritance
在他的" 有效Java"一书中,Joshua Bloch写了关于equals()派生类在检查中添加其他字段的合同中发生的陷阱.通常情况下,这会破坏对称性,但Bloch声明"您可以在不违反equals合同的情况下将值组件添加到抽象类的子类".
显然这是真的,因为没有抽象类的实例,所以没有违反的对称性.但是其他子类呢?我写了这个例子,故意省略哈希码实现和空检查以保持代码简短:
public abstract class Vehicle {
private final String color;
public Vehicle(String color) {
this.color = color;
}
public String getColor() {
return color;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Vehicle)) return false;
Vehicle that = (Vehicle) o;
return color.equals(that.color);
}
}
public class Bicycle extends Vehicle {
public Bicycle(String color) {
super(color);
}
}
public class Car extends Vehicle {
private final String model;
public Car(String color, String model) {
super(color);
this.model = model;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Car)) return false;
Car that = (Car) o;
return getColor().equals(that.getColor()) && model.equals(that.model);
}
}
Run Code Online (Sandbox Code Playgroud)
当我使用相同的颜色字符串创建每个类的一个实例时,对称性equals()被破坏:
Bicycle bicycle = new Bicycle("blue");
Car car = new Car("blue", "Mercedes");
bicycle.equals(car) <- true
car.equals(bicycle) <- false
Run Code Online (Sandbox Code Playgroud)
我不确定如何处理这个最好的方法.equals()在抽象类中声明为抽象,以在子类中强制实现?但是,通过equals ()在抽象类中完全不进行声明,可以实现同样的效果.
在这种情况下,Java 的 equals 契约变得特别参差不齐,最终这一切都取决于程序员的偏好和需求。我记得遇到过同样的问题,我遇到了这篇文章,它在考虑与 Java 的 equals 合同时讨论了几种可能性和问题。它基本上最终说没有办法在不破坏 Java 等价契约的情况下正确地做到这一点。
在处理抽象类时,我个人的偏好是根本不给抽象类一个 equals 方法。这没有意义。你不能有两个抽象类型的对象;你应该如何比较它们?相反,我为每个子类提供了自己的 equals,并且运行时equals()在调用时处理其余的。总的来说,我最常遵循的文章中提出的解决方案是“只能比较完全相同类别的对象”,这对我来说似乎是最明智的。