Overriding breaks Liskov Substitution Principle if you change any behavior defined by a base method. Which means that:
- The weakest precondition for a
child method should be not stronger
than for the base method.
- A postcondition for the child method
implies a postcondition for the
parent method. Where a postcondition
is formed by: a) all side
effects caused by a method execution and b)
type and value of a returned expression.
From these two requirements you can imply that any new functionality in a child method that does not affect what is expected from a super method does not violate the principle. These conditions allow you to use a subclass instance where a superclass instance is required.
If these rules are not obeyed a class violates LSP. A classical example is the following hierarchy: class Point(x,y), class ColoredPoint(x,y,color) that extends Point(x,y) and overridden method equals(obj) in ColoredPoint that reflects equality by color. Now if one have an instance of Set<Point> he can assume that two points with the same coordinates are equal in this set. Which is not the case with the overridden method equals and, in general, there is just no way to extend an instantiable class and add an aspect used in equals method without breaking LSP.
Thus every time you break this principle you implicitly introduce a potential bug that reveals when invariant for a parent class that is expected by the code is not satisfied. However, in real world often there is no obvious design solution that does not violate LSP, so one can use, for example, @ViolatesLSP class annotation to warn a client that it is not safe to use class instances in a polymorphic set or in any other kind of cases that rely on the Liskov substitution principle.