Java – how to obey the contract of equals() when deriving from an abstract class

Joshua Bloch wrote in his book "effective Java" that when derived classes add additional fields to checks, there is a trap in the contract about equals () This usually destroys symmetry, but Bloch points out that "you can add a value component to a subclass of an abstract class without violating the equals convention."

Obviously, this is true because there are no instances of abstract classes, so there is no violation of symmetry But what about other subclasses? I wrote this example and deliberately omitted the hash code implementation and null value check to keep the code short:

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);
    }

}

When I create an instance of each class with the same color string, the symmetry of equals() will be broken:

Bicycle bicycle = new Bicycle("blue");
Car car = new Car("blue","Mercedes");

bicycle.equals(car) <- true
car.equals(bicycle) <- false

I'm not sure how to deal with this best Declare equals () as an abstraction in an abstract class to enforce subclasses? However, no declaration of equals () in an abstract class can achieve the same effect

Solution

There are many equivalent contracts in Java under such circumstances, which eventually become a problem of programmers' preferences and needs I remember meeting the same problem. I met this article. Considering the equal contract with Java, several possibilities and problems appeared It basically ends up saying that there is no way to do this properly without violating the Java contract

When dealing with abstract classes, my personal preference is not to give abstract classes an equals method Meaningless, you can't have two abstract types of objects; How should you compare? Instead, I give each subclass its own equals, and the runtime handles the rest whenever equals () is called In general, the solution I most often follow in the article is "only objects of exactly the same class may be compared", which seems to me the wisest

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>