After a short discussion in the comments here I have come to wonder whether or not a baseclass like
Animal in the traditional OOP example should be marked as abstract or not.
Personally I believe it should: there is no such thing as an "animal", it is merely a term that groups certain subtypes based on what they are. Any instance of an "animal" should be a subtype, a concrete example.
The comment that followed on this was
There most certainly is such a thing as an Animal. Or would you insist that Dog be broken down into Affenpinscher, IrishWolfhound, SiberianHusky, EnglishSetter, and 600 other breeds?
which is a fair remark but that is different from the original situation where the hierarchy was
And there are no subclasses of
Dog in the first place. Should there have been then yes,
Dog should be abstract because the tree includes more specific leafs for that specific type.
I can only assume that the reason you wouldn't make it a specific subtype is when you simply don't know it. I would instead add a "default" implementation of a dog to account for this so I can keep the
Dog class itself abstract so there wouldn't be any ambiguity possible: you are forced to either create a specific dog or indicate that you don't know the type.
Furthermore it also allows you to create
abstract methods that every dog should implement for themselves because they are dogtype-specific. By using a non-abstract class you can't do this and you'll have to remember to override each method in the subclasses.
In the above tree I would make
Animal abstract and allow the others to be instantiated.
The question boils down to this: should you be able to instantiate a class that exists to indicate a subspecies or should you defer the creation of such a "general" object to a subtype?