A square is a rectangle

In OO it is commonly stated that it's inappropriate for Square to subclass Rectangle (i.e. that would represent improper inheritance). See for example the wikipedia article on the Circle-ellipse problem [].

Consider that model Rectangle has an constructor which takes a Square value, allowing for an implicit conversion from a Square value to a Rectangle value:


$model Square
{
    Point p1;   // bottom left corner
    float32 w;  // width and height
};

$model Rectangle
{
    Point p1;   // bottom left corner
    Point p2;   // top right corner

    // Note that this single argument constructor is not declared 'explicit' and therefore 
    // allows for implicit conversion from Square to Rectangle.
    $$(const Square& s) : p1(s.p1), p2(p1.x+s.w, p1.y+s.w) {}
};

This represents the fact that every Square value is a Rectangle value.

In a way Rectangle is kind of like a retrospectively defined supertype of Square because a Square value can be implicit cast to a Rectangle value. E.g.


Square s;
Rectangle r = s;

It is important to be aware that the sense in which Square is-a Rectangle is very different to the normal OO notion of subtype. The former relates to value substitutability (the set of Square values is a subset of the set of Rectangle values), and the latter relates to pointer to state machine substitutability (aka LSP) which would normally suggest no inheritance amongst value types is possible (e.g. under LSP one would conclude that a square is not a rectangle because a rectangle variable holding a square value can be reassigned such that it no longer holds a square value).