“A closure is a poor man’s object; an object is a poor man’s closure” (2003)
My definition of an object is "an ADT that gets to 'decide', using private runtime state, what to do in response to any/all attempts to interact with it."<p>Which makes for a very simple test: if something is an object, you should be able to send it a message that makes it change its mind about what messages it accepts after that.<p>There's no obvious way to implement a behavior like this using the native "objects" in nominally-object-oriented languages like C++ or Java. (But you <i>can</i> do so with the closure types from these languages. Or you can look higher on the stack: threads with IPC queues, or POSIX <i>processes</i>, are both objects.)<p>But implementing this behavior is obvious in Ruby; this is how basic things like Object#extend work.<p>And implementing this behavior is also obvious, oddly enough, in Erlang: <a href="http://joearms.github.io/2013/11/21/My-favorite-erlang-program.html" rel="nofollow">http://joearms.github.io/2013/11/21/My-favorite-erlang-progr...</a><p>In conclusion, Erlang is more object-oriented than Java. ;)<p>---<p>And yeah, I know, this definition of OOP-ness sort of flies in the face of decades of things people have said about OOP. Objects, under this definition of OOP, don't obey any of the SOLID principles. They're slippery; unpredictable; "alive."<p>But this was the original definition! It's the one Smalltalk fits; it's the one LambdaMOO fits; it's what is meant by referring to Javascript as object-oriented.<p>It's a shame we have this collision between meanings; having two separate words for "OOP like Smalltalk" and "OOP like Java" would have saved language-designers all a world of arguments from people who try to propose extensions to a language in one category, assuming it's in the other.