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) |
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.
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.
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.)
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.)