OOP is not about nouns. It's about establishing protocols between subsystems. What you're describing are the typical fake "dilemmas" of someone coming from a static, class-oriented programming languages like Java.
Look up Class Responsibility Collaborator exercise.
Is that what it's about? I try to establish protocols between subsystems without OOP quite often. Are you referring to message passing specifically?
I'm pretty sure most people who strongly like OOP are sure their particular definition is the correct one. I haven't seen many people agree about what that definition is though. I generally dislike OOP, but perhaps that's because my definition is "encourages implementation inheritance". As you're keen to note, the standard list of other things (encapsulation, message passing, dynamic dispatch, interface inheritance, and even "establishing protocols") are available in a lot of other languages which people don't generally consider OO.
Perhaps I'm ignorant, but I like my way of doing things, and a.f() is less attractive to me than f(a) for all the reasons I listed.
Or maybe it tells you that the benefits of OOP are different from what they're theoretically supposed to be. What I read from the thread is that there seems to be significant psychological appeal to some in the noun-verb way, and OOP (perhaps unintentionally) satisifies that need. (And that helps me understand the frequent "Julia needs a thing.do() syntax" complaint on the Julia forums, and why telling them "semantically do(thing) does the same thing" doesn't seem to work.)
canvas pen brush circle draw
There aren't many languages which support multimethods, but overloading functions is sufficient for statically typed cases, and it's appealing (for me) to have the same syntax for "builtin" methods and ones you add yourself:
Other people have mentioned languages with "uniform function call" syntax (where f(a) and a.f() are synonyms). I guess that's ok if you're in the "there's more than one way to do it" camp. I don't think that completely addresses the problem though. I could make more examples, but this post is getting long already.For what it's worth, I really dislike it when languages implement operator overloading for binary operators as methods on the first object without a way to dispatch to the second object. This makes it very difficult to have your new types play well with the builtin or library provided types. Binary operators really are functions with two arguments.