The one thing that I've seen developers have trouble grasping is that the advantage of inheritance and polymorphism is code reuse.
Not in the sense of code reuse by the derived class reusing the functions of the base class.
Rather in the sense of users of the base class not having to change their code when given an object of the derived class.
This substitutability is sometimes called the Liskov Substitution Principle.
It's hard to see the value of it in a small contrived example program. But it is an important capability in object-oriented programming for non-trivial programs.
One project I worked on, which been on-going for 10 years by the time I joined the team, had used inheritance for code reuse of the base classes by the dozens and dozens of derived classes. This kind of "code reuse abuse" meant that all the callsites had to check the object to see what type of object was being worked with, so the caller could do the THIS thing rather than the THAT thing with the object. That was a mess.
Ergo one form of what I call "DRY spaghetti". :) Good insight.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.