## Equals method and LSP violation

Moderatoren: pmueller, SE - Design and Construction

tud_std
Erstie
Beiträge: 19
Registriert: 13. Apr 2016 16:29

### Equals method and LSP violation

Hi,

In "Effective Java 2nd edition", page 40, It says that the getClass-based equals method violates Liskov Substitution Principle. Following is the super-type Point and subtype CounterPoint source code :

Code: Alles auswählen

public class Point {

private final int x;
private final int y;

public Point(int x, int y) {
this.x = x;
this.y = y;
}

@Override public boolean equals(Object o) {
if (o == null || o.getClass() != getClass())
return false;
Point p = (Point) o;
return p.x == x && p.y == y;
}
}


Code: Alles auswählen

public class CounterPoint extends Point {
private static final AtomicInteger counter = new AtomicInteger();

public CounterPoint(int x, int y) {
super(x, y);
counter.incrementAndGet();
}

public int numberCreated() {
return counter.get();
}
}

Could you please elaborate further on why the given equals method violates LSP and what important property or properties of supertype Point, does not or do not hold for the subtype CounterPoint. Many thanks.

Regards.

0b101101101
Endlosschleifenbastler
Beiträge: 179
Registriert: 15. Apr 2015 18:24

### Re: Equals method and LSP violation

LSP says, that an instance class should be substitutable with an instance of a subclass without change of behavior. Take the boolean b=(Point(0,0).equals(Point(0,0))). If we substitute one Point with a CounterPoint as in b=(Point(0,0).equals(CounterPoint(0,0))), the value of the boolean has changed.

For completeness, note that does not mean you can never use getClass in equals, because:
eichberg hat geschrieben:
23. Nov 2017 13:42
If a class is effectively final (i.e., it is not possible to write subclasses of it) and all superclasses of it are abstract (or are interfaces) then it doesn't matter.
The reason is, that if you cannot create a subclass or superclass of another class, then you can never give them to equals, so it does not matter, whether you use isinstanceof or getClass==getClass inside equals.

However, In your case you obviously have a class and a subclass (Point and CounterPoint).

Finally, note that there may be other contracts that a class declares in their documentation about the equals-method. I can imagine for example a Double-class that specifies that the NaN value is never equal to anything (you can try it in javascript: NaN==NaN --> false). And I guess, if upholding LSP for the contracts in the documentation conflicts with standard LSP (e.g. if you cannot do both), then the contract is more important. However, I'm not sure about that.

tud_std
Erstie
Beiträge: 19
Registriert: 13. Apr 2016 16:29