I come originally from games programming and while it might seem to fit to have mammals
and animals
and so forth as abstract concepts in a game engine, I've found fewer worst cases than games where you want to obliterate all those abstractions and reach around them.
The problem in my opinion is with the concept of "is". A proper inheritance hierarchy that conforms to principles like Lisksov substitution revolves around the concept of substitutability. Yet we don't want to downcast away the abstraction down to the concrete, but we don't want the concrete details to leak into the abstraction. So we're trying to determine what something can do based on what it roughly is, but not what it actually is. Yet what is "roughly is" isn't often enough information to do what we want to do with it (ex: determine if two animals can reproduce with each other), but what "actually is" gets us too far, since there might be many things that aren't "actually "are that thing but have the same functionality available, so why should we have to check and sprinkle redundant code in our codebase?
If we want to model human intuition, then the functionality that things have are never based on what they "are". It's based on what they "have". A biped with crippled legs can't walk upright. It doesn't matter that is a form of biped, or that bipeds can usually walk. A broken microwave can't heat food up even if it's a type of microwave. A mute human can't talk. It doesn't matter that they are human. It's based on what things "have", not what they "are", that determines what they are capable or incapable of doing. It's based on having functional legs that can allow something to walk.
The broad problem I find with inheritance which narrows its most natural applicability to limited contexts is that it wants to say what things can do based on what they "are", not what they "have". And that can get us reaching for the most granular concept of determing is something is a form of "IWalkable", to determine if something can walk, when we're really just concerned if they "have" functional legs. And inheriting/implementing from IWalkable typically removes the ability from being able to remove it at runtime if a person trips over a rock and breaks both of their legs.
What is a dragon, you know? Is it a type of bird? A type of reptile? Both? Neither? If we have an established inheritance hierarchy, we might debate for ages. Or maybe we don't and still try to base it on interfaces like it's "IQuadruped", and "IFlyable", and "IFireBreathable". But what if its wings are crippled? We can debate endlessly, and we're trying to reach a wavelength with the rest of the team. And in my opinion, the reason that connection is elusive is that we're focusing on what it "is". How about we talk about what a dragon "has"? It can have, at least initially, super-strong scales, wings that allow it to fly, four legs that can allow it to walk on the ground, some internal engine that allows it to breathe fire. We probably won't debate too much on what it "has". And we can leverage much more in the way of polymorphism if we revolve it all around what it "has", not what it "is", without changing our minds later.