Firstly, it's my belief that OO principles (such as the LSP) are called "principles" and not "laws" because, as opposed to laws, they can be subject to interpretation (check out the discussion here), and are something that it's more to be desired rather than a state that should always be so.
That being said, in the specific context of your question, I do believe that having various implementations of the same interface, which may result in either technically or functionally non-consistent behavior is a violation of the LSP and a thing not to be desired. Here's a small example :
Imagine you have some API that declares an interface like so:
public interface RightAngledShape {
public void setWidth(int width);
public void setHeight(int height);
/**
* This method calculates the perimeter of a shape having only right angles and the width and height as set
* via the {@link RightAngledShape#setWidth(int)} and {@link
RightAngledShape#setHeight(int)} methods
*
* @return the perimeter of the corresponing right-angled shape
*/
public int getPerimeter();
}
Imagine then that there's also two implementations of the interface like so:
public class Rectangle implements RightAngledShape {
private int width,height;
@Override
public void setWidth(int width) {
this.width = width;
}
@Override
public void setHeight(int height) {
this.height = height;
}
@Override
public int getPerimeter() {
return 2*(width + height);
}
}
and:
public class InvalidSquare extends Rectangle {
public void setHeight(int height) {
super.setWidth(height);
super.setHeight(height);
}
}
In certain contexts this might be a good thing. Someone might need Square and Rectangle implementations only to store the width and height values, for which case having a Square that simply overrides the Rectangle methods in order to enforce a single size for all sides is a good thing. But since these two implementations are also of type RightAngledShape the LSP says that they should fully obey its contract and have the getPerimeter() method return the correct perimeter all the time. In the above example this does not happen:
public static void main(String[] args) {
RightAngledShape shape1 = randomFactoryMethod1();
shape1.setWidth(10);
shape1.setHeight(20);
System.out.println(shape1.getPerimeter());//prints 60
RightAngledShape shape2 = randomFactoryMethod2();
shape2.setWidth(10);
shape2.setHeight(20);
System.out.println(shape2.getPerimeter());//prints 80
}
static RightAngledShape randomFactoryMethod1() {
return new Rectangle();
}
static RightAngledShape randomFactoryMethod2() {
return new InvalidSquare();
}