I agree. IMO, Java-style OOP conflates 2 different concepts, polymorphism and inheritance.
Polymorphism (including dynamic dispatch and duck typing) is a game changer, in that it encourages simple, stable interfaces, enables testing, encourages encapsulation, etc. It's a key technique for building big projects.
Inheritance is a tool for reducing the amount of code written by a human, among many others (things like code generation and composition) I haven't seen it unlock other important conceptual domains the way polymorphism does.
Unfortunately many undergraduate curriculums get overly excited about inheritance when teaching OOP. I guess animal-cat-dog is an easy example (though totally unrealistic), but the problems polymorphism solves don't often show up in classroom-sized projects.
Polymorphism (including dynamic dispatch and duck typing) is a game changer, in that it encourages simple, stable interfaces, enables testing, encourages encapsulation, etc. It's a key technique for building big projects.
Inheritance is a tool for reducing the amount of code written by a human, among many others (things like code generation and composition) I haven't seen it unlock other important conceptual domains the way polymorphism does.
Unfortunately many undergraduate curriculums get overly excited about inheritance when teaching OOP. I guess animal-cat-dog is an easy example (though totally unrealistic), but the problems polymorphism solves don't often show up in classroom-sized projects.