约书亚·布洛赫在他的书“有效
Java”中写道,当派生类向检查添加附加字段时,关于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); } }
当我使用相同的颜色字符串创建每个类的一个实例时,equals()的对称性将被破坏:
Bicycle bicycle = new Bicycle("blue"); Car car = new Car("blue","Mercedes"); bicycle.equals(car) <- true car.equals(bicycle) <- false
我不确定如何处理这个最好的方法.在抽象类中声明equals()作为抽象,以强制执行子类?但是,在抽象类中根本没有声明equals()可以实现相同的效果.