Liskov Substitution Principle – Strengthening Preconditions

designliskov-substitutionobject-orientedsolid

I am a bit confused as for what it really means. In the related questions (Is this a violation of the Liskov Substitution Principle?), it was said that the example clearly violates LSP.

But I wonder, if there is no new exception thrown, would it still be violation? Isn't it simply polymorphism then?
I.e:

public class Task
{
     public Status Status { get; set; }

     public virtual void Close()
     {
         Status = Status.Closed;
     }
}

public class ProjectTask : Task
{
     public override void Close()
     {
          if (Status == Status.Started) 
          {
              base.Close(); 
          }
     }
}

Best Answer

It depends.

For validating the LSP, you need to know the precise contract of the Close function. If the code looks like this

public class Task
{
     // after a call to this method, the status must become "Closed"
     public virtual void Close()
     //...
}

then a derived class which ignores this comment violates the LSP. If, however, the code looks like this

public class Task
{
     // tries to close the the task 
     // (check Status afterwards to find out if it has worked)
     public virtual void Close()
     //...
}

then ProjectTask does not violate the LSP.

However, in case there is no comment, a function name like Close gives IMHO a the caller a pretty clear expectation of setting the status to "Closed", and if the function then does not work that way, it would be at least a violation of the "Principle of least astonishment".

Note also that some programming languages like Eiffel have in-built language supports for contracts, so one does not necessarily need to rely on comments. See this Wikipedia article for a list.