I don't agree with this, and I'm personally an anti-OOP militant.
Inheritance isn't the root of all evil, dynamic dispatch is. It's a remarkably powerful implementation detail but one with enormous cost, regardless of whether you're using an AoT/JIT compiled or interpreted language.
As opposed to passing function pointers everywhere, callback hell and friends? Or which language does it well in your opinion? The fact is, dynamic dispatch is needed, because not everything can be known at compile time. And as in a recent thread a HNer rightly noted (could not find it where I read it), the actually expensive thing in programming is flexibility.
Devirtualization optimizations can turn semantically "dynamic" dispatches into static dispatches, but sometimes you really just need a dynamic dispatch. Note that a dynamic dispatch doesn't have to be anything more than a branch. Further, sometimes devirtualizing everything leads to enormous binaries and compile times. Runtime performance isn't everything, and it's typically better to opt-into devirtualization rather than to opt-out of it.
You must have absurd standards if you find dynamic dispatch to be unacceptably slow. Also, yeah, not every function call needs to be inlined. One level of indirection on top of jumping into a new function isn't really much overhead at all, unless you're doing it for literally every function call.
> Inheritance isn't the root of all evil, dynamic dispatch is. It's a remarkably powerful implementation detail but one with enormous cost ...
Dynamic dispatching typically costs one pointer lookup in a vtable[0]. By "typically", I specifically mean "in any production quality run-time environment." This is not an "enormous cost" by any reasonable definition.
Disagree. Go and Rust both have dynamic dispatch and neither have the problems that inheritance has. Even in C which lacks dynamic dispatch, people will either try to build it at the expense of type safety or they will try to manage an impossibly complex implicit state machine (I've seen this in a lot of critical real time systems).
Inheritance isn't the root of all evil, dynamic dispatch is. It's a remarkably powerful implementation detail but one with enormous cost, regardless of whether you're using an AoT/JIT compiled or interpreted language.