0

Consider this example:

public class SimpleValidator
{
    public virtual bool InRange(int x)
    {
        return x >= 6 && x <=12;
    }
}

public class OffsetAwareValidator : SimpleValidator
{
    int offset = 0;

    public OffsetAwareValidator(int offset)
    {
        this.offset = offset;
    }

    public override bool InRange(int x)
    {
        var num = x + offset;
        return num >= 6 && num <= 12;
    }
}

Now, obviously, new OffsetAwareValidator(0) will have the exact same behavior as SimpleValidator. However, when offset is non zero, some values that pass validation in OffsetAwareValidator would not pass it in SimpleValidator.

Is this a violation of LSP?

4

The only way this violates LSP is if the contract for SimpleValidator requires that it return the same answers for the same inputs.

If the contract is merely, "must return either true or false, never throw, and have no side effects", then LSP isn't broken.

-- In Response to a Comment --

If you reverse the inheritance hierarchy, then you remove the need for the SimpleValidator completely (caution: I don't know C#, I'm just guessing on the syntax):

public class Validator {
    int offset = 0;

    public static Validator SimpleValidator() {
        return Validator(0);
    }

    public Validator(int offset) {
        this.offset = offset;
    }

    public bool InRange(int x) {
        var num = x + offset;
        return 6 <= num && num <= 12;
    }
}
  • 1
    This leads to question whether OffsetAwareValidator shall pass the same unit tests as superclass? – Grzegorz Sławecki Mar 4 '16 at 12:28
  • 1
    A class can be more restrictive in what it returns and still satisfy LSP. So if your unit tests were designed to test a contract that is more restrictive than the inRange contract actually is, then OffsetAwareValidator might fail the tests and still satisfy LSP. If you had a Validator interface, the tests for it would likely be different than the ones that SimpleValidator has. – Daniel T. Mar 4 '16 at 12:36
  • 1
    It's been almost two weeks, but I've finally found what's wrong with my example. The order of inheritance is wrong. It's actually OffsetAwareValidator that is more generic thing. – Grzegorz Sławecki Mar 14 '16 at 15:51
  • If the only difference between your class and sub-class is data, then the sub-class probably doesn't need to exist. I also responded to your swapping hierarchies comment in the answer. – Daniel T. Mar 14 '16 at 16:00
  • The comment You've added seems to be right in this example. However, should any behavior exist in these classes, I believe there could be a good reason to have inheritance. The subclass (SimpleValidator) could probably have the behavior implemented more efficiently to handle the specific case. However, I'm aware that i'm starting to float away from the point of this question. – Grzegorz Sławecki Mar 14 '16 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.