CLOS is probably the best, if you ignore the fact that built-in types aren't actually objects. (They can pretend to be, but aren't. You also can't make built-in functions generic, which is quite annoying.)<p>Moose is a close second, and provides a lot of sugar that I really wish I had in CLOS. Roles are pretty much mandatory for proper OO these days, and Moose is the only production system that has them. I also love sugar like lazy_build. The type constraint system is just wonderful.<p>Continuing down, Ruby is a bit better than Python, but both are workable. They give you what you would expect from class-based OO, and you have a basic MOP, too.<p>At the bottom are Java, C++, and PHP. This style of "OO" barely resembles OO. Java is probably the worst here, but C++ makes it very hard to do things right. PHP's design simply makes no sense at all. None have any useful MOPs to speak of, unless you consider "reflection" a metaobject protocol.<p>Smalltalk is a special case; it is obviously pure OO, but the features it provides to the programmer are less numerous than other systems. Smalltalk is what Java should have been, before Java was even conceived.<p>Anyway, my advice is to try them all and decide what you like best. CLOS has features I wish Moose had, and Moose has features I with CLOS had, but they are both quite usable, and allow me to model my program cleanly. It is also easy to steal features for one from the other.<p>The key feature of Moose and CLOS is their extensive MOP, which lets you tweak or completely override nearly every feature of the object system. Instance storage, method calls, attribute behavior, etc., etc., is all implemented in "itself". The end result is that you can extend the object system with the object system that you are extending. This is powerful because it means your extensions can be written in your extensions, making for code that works exactly how you desire. No compromises. (Moose is an object system built on top of Class::MOP, and it is possible to write Moose extensions in Moose. Excellent!)<p>Python and Ruby have a MOP, but it is not as featureful. Compare the availability of meta-object-protocol extensions for CL, like Elephant and Context; and for Perl, like the entire MooseX:: namespace; with extensions available for Ruby and Python. It is just not close<p>Even if you don't care about the MOP for yourself, you will care about how easy it makes writing useful libraries. Most of the MooseX:: modules you will find compose and work perfectly with other MooseX:: modules. The metaobject protocol makes sure everything stays compatible.<p>Personally, when I start using object systems other than Moose and CLOS, the implementation details get in the way of writing good code. I avoid them when possible. (If you haven't used Moose or CLOS, please don't reply and say, "oh, Java is fine, you're using it wrong". You don't know enough to make that argument.)