https://en.wikipedia.org/wiki/Design_Patterns
Don't take undergraduate OOP courses seriously.
which isn't an explanation, but just the same as the OOP mantra that was taught in undergraduate courses.
The problem is what if you have a class that needs to derive behavior that's in two (or more) classes? Multi-inheritance is terrible because it becomes a nightmare of which class overrides which.
If there's a shallow level of inheritance (1-2 levels deep), then there's nothing wrong with it. Things like composition for most use cases has been common advice since forever.
What happened with java was that there was a massive movement for enterprise code that way over-complicated everything based on ideas that didn't pan out. There were all these auxiliary patterns, and ideas that people had to learn to be onboarded onto projects, and so many people poorly understood them that it led to even more spaghetti code, too many people that developed using dogma instead of common sense.
Remember that OOP and inheritance to some extent came out of the need to develop GUI systems. Inheritance is still heavily used in GUI toolkits because it's a good fit for that problem space. You have graphs of objects that need to be treated at different levels of abstraction, and controls often need to customize (override) or implement some behavior that shouldn't itself be a part of the public API.
Attempts to get rid of inheritance and OOP in UIs end up looking like Compose or React. I found very quickly when working with these that pure composition just wasn't sufficient and these approaches have their own issues; problems that OOP trivially solves become difficult to impossible to solve cleanly without it.
The problem is when things change. A simple example - you build a classification of all life and it is built upon the idea that everything "is a" plant or animal. And then one day it turns out there are fungi. This is not a fun situation to deal with and inheritance makes it a lot harder because the "is a" relationship is driving a ton of your logic.
IDK I don't want to get to into it beyond that, many people have written quite a lot on the topic.
In a more flexible type system with union types and other magical features, your example problem would be less of an issue.
However Java has an extremely limited type system so there is no middle ground between composition and inheritance. Once you choose one way, there is no “middle step” to migrate over.
With all due respect, this and similar examples are just plain wrong, and I really can't take anyone seriously when that example is used. The point of programming, and its abstractions is to help you complete a task, and make the implementation maintainable and easy to reason about. I think grabbing the "is a" part is fundamentally bad -- there is no point in creating a taxonomy in and of itself, this is no database for that data. Inheritance sometimes is the correct abstraction and while it is definitely overused, when it's correctly applied there isn't really another abstraction that would fit better. E.g. see a graphics library's Node class as the stereotypical correct application.
1. That my point is bad for some reason
2. That inheritance is sometimes a great tool
We agree on (2). Inheritance is pretty amazing, even if I think that it's ultimately a terrible feature to build so ingrained into a language and to expand in power to such a degree.
As for (1), I don't really get your point. Abstractions help you complete a task - ok. Abstractions are to help you reason about stuff - ok. Something about "is a" being bad? None of that really explains why my example demonstrates the problems you run into when you try to build a classification of values using inheritance. But I also said that I wasn't going to really try to explain much, it's been written about plenty.
Judicious OOP design allows others to change behavior based upon needs that perhaps the original coder never thought of.
I would not call most Java OOP design judicious. The control in Java is owned by the library writers and the language devs -- not the people using it.
But it is quite advantageous when, as you say, your model is well thought out and stable.