Strongly-typed languages like Java or C# really obscure this simple truth, in my opinion. What the OP is talking about is one specific way that it can be obscured. Which is certainly true as far as it goes. But it's not going far enough!
The real problem is that OOP is totally under-constrained for end-user applications. (Although it's perfectly adequate, I think, for modeling formats and protocols).
The only really good way to do applications is as dynamic functions, because there is self-similarity between your program statements and the way you organize them, making your combinatorial problem far more straight-forward. Plus, if you do it right, your function set can fit into on-die cache, and you know enough about your inputs so that you can allocate a fixed, small memory space for any combination of statements are required for a given input (or gracefully error out when your assumptions about input are violated - ideally without even unloading your code).