Consider the diagram :
Collection - an abstract class with the common part of all the others: abstract functions that put an integer in a collection and check whether the collection is empty.
Bag - a class that implements the collection as a hash, where you can find elements easily. Each element may appear more than once
I need to determine if this inheritance relationship maintain the Liskov Substitution principle.
So, i start with check if the signatures of the function are the same and they are. (put() and isEmpty()). After that, i check if the methods contracts of the two are the same, but can i have contracts to abstract class? i can't 'create' it. if they are, it's enough to say that these two class maintain the LSP? or something else is needed?
The Liskov Substitution principle is one of the 5 basic principles for good object-oriented design (AKA SOLID):
The principle stated by Barbara Liskov says that Functions that use pointers of references to base classes must be able to use objects of derived classes without knowing it. It is a good design principle because when a function does not conform to the LSP, then it must know all the possible derivatives of the base class.
The importance of this principle becomes obvious when you consider the consequences of violating it. Let's make an example. Suppose we are developing a program dealing with shapes. We have created the class Rectangle and, when designing class Square, we think natural of inheriting from class Rectangle:
Using C++ we would write:
class Rectangle
{
public:
virtual void SetWidth(const double w) {width_=w;}
virtual void SetHeight(const double h) {height_=h;}
virtual double GetHeight() const {return height_;}
virtual double GetWidth() const {return width_;}
private:
double width_;
double height_;
};
class Square : public Rectangle
{
public:
virtual void SetWidth(const double w) {
Rectangle::SetWidth(w);
Rectangle::SetHeight(w);
}
virtual void SetHeight(const double h) {
Rectangle::SetWidth(w);
Rectangle::SetHeight(h);
}
};
void function (Rectangle& r)
{
r.SetWidth(5);
r.SetHeight(4);
assert(r.GetWidth() * r.GetHeight()) == 20);
}
As it is clear from the example, the assertion (and the Liskov project) is violated due to the fact that the Rectangle has a property (independency of the size of height and weight) which does not hold for a Square.
To answer your question, you should reason about properties that hold for the base class but not for the derived classes. If the interface is well designed (as it seems), you won't find any and you'll be able of substituting the base class with any derived class.