Ruby versus Smalltalk versus Objective-C versus C++ versus Java versus Python versus CLOS versus Perl5 versus XOTcl

Thanks to the following people for helping/correcting mistakes: Stefan Schmiedl (checking all and Lisp column), Clemens Hintze, Albert Wagner, Paul Prescod (Python column), Mathieu Bouchard (Perl5 column), Clemens Wyss,Tarun Ramakrishna Elankath, Michael Austin (Objective-C), Mark Aufflick (Perl5), Travis Griggs (Objective-C), Michael Schlenker (XOTcl), Cliff L. Biffle and Dog Way. Milan Maksimovic suggested adding Templates. Are the templates entries correct?
Please email me about any other mistakes. armin(at)approximity.com (Armin Roehrl).

The idea is stolen from here. I added Java and Ruby, but also modified some entries, but Mr. Dekorte, the original author is far more competent, esp. in Objective-C, so I might have made a mistake by not having the same definition for the same terms. Hopefully this chart will help you compare and make a well-informed choice as to what would be better for you. One possible source of error is also that different dialects of the same language support different features: e.g. POC supports Garbage Collection.

One possible source of error is also that different dialects of the same language support different features: e.g. POC supports Garbage Collection.

  Ruby Objective-C SmallTalk-80 C++ Java Python CLOS Perl5 XOTcl
Typing dynamic dynamic/static dynamic static static dynamic dynamic mostly dynamic dynamic
Runtime access to method names yes yes yes no yes yes yes* yes yes (including method definitions)
Runtime access to class names yes yes yes no yes yes yes* yes yes (including class definitions)
Runtime access to instance variable names yes yes yes no yes yes yes* yes yes
Forwarding yes yes yes no no (?) yes ?? yes yes
Metaclasses yes yes yes no yes yes meta objects no yes
Inheritance mix-in single single multiple single multiple mix-in multiple mix-in, multiple (per object or per class)
Access to super method super super super Superclass::method super (Python 2.1 syntax): super(MyClass,self).methodName call-next-method SUPER::methodName next
root class Object Object (can have multiple) Object (can have multiple) none Object none t "UNIVERSAL" package Class/Object
Receiver name self self self this this self none, true generic functions $_[0] [self]
Private Data yes yes yes yes yes yes no no no
Private methods yes no no yes yes yes no no no
Class Variables yes no yes yes yes yes yes yes yes
Templates not needed(1) not needed not needed yes no not needed not needed not needed not needed
Garbage Collection yes yes yes no yes yes yes reference counting optional with volatile keyword (reference counting)


Comments about Python from Paul Prescod:
Super is not a keyword so you need to tell it what method it is syntactically contained in (but then you can use it anywhere you want without worrying about syntactic contex).

There are things you could argue about like private data/methods -- you can get at them but you need to do extra work to do so(as in most other languages). Garbage collection: yes, except in very rare situations involving deterministic finalizers in a cyclic loop (which finalizers do you run in what order?).


Comments about Lisp from Stefan Schmiedl:
runtime access is dependent on compiler behaviour, but generally yes. super methods: clos offers method combination, i.e. you can specify that in a subclass a method is run :before or :after the main method is run, if necessary, you can also specify :around methods, see clhs.


1]> (defclass a () ())
#
[2]> (defclass b (a) ())
#
[3]> (defmethod c ((dings a)) (princ "a"))
#)>
[4]> (defmethod c ((dings b)) (call-next-method) (princ "b"))
#)>
[5]> (defmethod c :after ((dings b)) (princ "c"))
#)>
[6]> (c (make-instance 'a))
a
"a"
[7]> (c (make-instance 'b))
abc
"b"


(1) about templates and ruby: You can create classes at runtime. Templates are not part of the language as it does not make much sense (due to dynamic typing). And even though you can, there's a gap to be filled between that and parametrized classes/types. Look at Mathieu Bouchard's RubyX11.


Mathieu Bouchard:
perl 6 is supposed to have both multiple and mixin inheritance. perl 6 is still mostly vapourware, but i think there's an experimental version ("perl 5+i") that has that feature.

If I want to classify OO languages, one way to do it is like this:

object-centric: Self, JavaScript, ...
class-centric: SmallTalk, C++, Java, ...
method-centric: CLOS, Dylan, ...

Another reason why CLOS is relevant is that it had two-thirds of the features of Aspect-Oriented Programming for about ten years before it became a buzzword. (and buzzword is relative: it is on ruby-talk...)


Tarun Ramakrishna Elankath:
Java has Metaclass support which is contrary to what you mention. Each object has a class object, and operations can be invoked on it similar to any other object.


Michael Austin:
I believe there is a mistake in the chart regarding the Objective-C column. I'll admit I've only been using Objective-C for around a year now but I'm almost positive that there is no language support for private methods in Obj-C.

I think the closest Objective-C comes to having private methods is "hidden" methods.

Basically, stick any methods you'd want to be private in a category, which adds methods to a particular class. Any methods declared & implemented outside of the class header and implementation files (such as a category file) are sort-of private, but they can still be called from anywhere.

This is why I've been able to call undocumented, and thus, "hidden" methods from Apple's frameworks (namely Cocoa), despite the fact I'm sure ideal programming technique would frown upon it.

The best you can hope for is to hide a class's methods from other programmers (in a category), but that's not much help seeing as how if you were really determined, you can just do a class dump to see everything.

If your definition of "private" is that an a particular method absolutely can not be called outside of the classes own methods, then Objective-C does not have private methods.

If you feel that "hidden" counts as "private", then I guess you can ignore this note.


Mark Aufflick:

In Perl, there is no distinction between the *definition* of a package or a class. Whether the user of that cod interacts with a sub as a package function or a class method depends purely on the syntax chosen when calling the sub.

Having realised that, in the case that a perl package is being used in an OO context, a package scope variable is actually a class variable.

    package Foo;

    my $counter;

    sub incrementClassCounter {
       $counter++;
    }
And then in the code using this class:
  use Foo;
  Foo->incrementClassCounter();
will behave exactly as you would expect a class variable to. If code from another class (say a subclass) wanted to access that variable directly, the syntax:
    print Foo::counter;
would do exactly that. There are also ways to introspect a package/class name to determine what variables (and methods) it has.

Now one slight issue with the syntax I showed above is that the variable is only directly visible inside that package name within the file it was defined. If class code is to span multiple files, the "my" variable declaration would be replaced by an "our" declaration. The "our $counter;" variable declaration would be required in all the class files, but would refer to the same actual variable and behave esactly as you would expect.

So my belief is that your table should indicate a 'yes' for perl5 class variables.


Travis Griggs

Got pointed to your site from a #smalltalk irc channel. I liked it. One thing I might note is that the nominal Objective-C garbage collection mechanism is ref-counting (you make that distinction for the Perl5 column). Not only that, but you have to code for it (i.e. explicit retain/release calls). Some might argue that you can compile Objective-C with the boehm-weiser collector, which I regularly do. But it is definitely the community supported approach. And if you were to make that argument, the same is true for C++.


Michael Schlenker:

Your comparision makes no real sense for pure Tcl, as Tcl is a procedural language (at least currently, OO based on the XOTcl extension will be added in the upcoming Tcl 8.5 release scheduled for next year).

But Tcl has a wealth of OO extensions, which provide rather different OO flavours to the Tcl programmer:

XOTcl is the most powerful of those, probably on par or above Ruby in expressivness and features (and speed). So probably take a look at the xotcl web site (especially the tutorial) or ask on their mailing list, I cannot easily say how your 'features' comparision might map to XOTcl..., but i can try.

There are some other powerful features in XOTcl not listed in your comparision, take a look at the XOTcl website (things like assertions, filters, nested classes etc.)


-Cliff L. Biffle:

One of your readers insisted Java had metaclasses, because "Each object has a class object, and operations can be invoked on it similar to any other object."

This is true, but it doesn't mean the language has metaclasses. Each class object is a direct instance of Class, with the operations defined on java.lang.Class.

If the language had metaclasses, foo.getClass() would return an instance of some metaclass FooClass, which would sport the class methods (in Java terms, static methods). In Java, even if you define a static method doSomething(), you cannot run foo.getClass().doSomething().

(Technically speaking, Java doesn't actually *have* class methods. Static methods in Java are closer to free-floating functions -- they're not inherited, they're not called on an object (even a class object), etc. Compare with Ruby or Smalltalk's class methods.)



Ruby slides.
Back to Approximity.
Futurometer

Other interesting comparisons