java – 从抽象类派生时如何服从equals()的合约

约书亚·布洛赫在他的书“有效 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()可以实现相同的效果.

解决方法

Java的等同契约在这样的情况下特别多,最终这一切都成为程序员的偏好和需求的问题.我记得遇到这个同样的问题,我遇到了 this article,考虑到与Java的平等合同时,它出现了几个可能性和问题.它基本上最终说,没有办法适当地做到这一点,而不违反Java等于合同.

在处理抽象类时,我个人的喜好是不要给抽象类一个equals方法.没有意义你不能有两个抽象类型的对象;你应该怎么比较呢?相反,我给每个子类自己的equals,并且运行时处理其余的每当equals()被调用.总的来说,我最经常遵循的文章中提出的解决方案是“只有完全相同的类的对象可能被比较”,这似乎对我来说最为明智.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...