Nice.
One metaphor that I like to use in OO is that inheritance is best used to "fill in holes." Imagine that an abstract class is a class with holes in it (i.e., the abstract methods). Subclassing fills in the holes and gives you a complete class. That is really the best use of inheritance. If you override, you have a higher chance of breaking behavior via a Liskov Substitution violation.