A couple of other comments have argued that "ontological inheritance" and "abstract data type inheritance" are actually the same thing: > This is because Squares are Liskov substitutable for Rectangles... which is because Squares are, platonically, a kind of Rectangle. > If the type system is sound and expressive enough, ontological inheritance ( this thing is a specific variety of that thing) and abstract data type…
Yes! The thing that ends up breaking in the squares and rectangles examples is mutability. Remember that math things are immutable by default. This thing is a square, and by definition also a rectangle, and since its properties and identity are immutable, that will always be true. However, programming takes those immutable concepts and tends to make them mutable. So now we have a rectangle, and we can change its iden…
Mutability isn't sufficient.
Breakage requires more than mutability. In dynamic languages, a mutated object can retract its squareness (smalltalk `become`; javascript __proto__ assignment; python object self-mutation). And predicate types (it's a Square iff its sides are the same length) are even graceful.
So I'd rephrase that as "if a specific implementation can mutate in ways that invalidate the laws expected of it, and you can't mutate the laws expected of it to match, your implementation might not match expectations". "Might not", because relaxed and pruned expectations may be locally sufficient.