torsdag, maj 29, 2008

Ruby doesn't have meta classes

OK. It's time to get rid of this terminology problem. Ruby does NOT have meta classes. You can define them yourself, but it's not the same thing as what is commonly called the meta class. That is more correctly called the eigen class. The singleton class is also better than meta class, but eigen class is definitely the most correct term.

So what is a meta class then? Well, it's a class that defines the behavior of other classes. You can define meta classes in Ruby if you want too by defining a subclass of Class. Those classes would be metaclasses.

Edit: Of course, if you actually try to define a subclass of Class you will find that Ruby doesn't allow you to do that, which means that you don't have any meta classes in Ruby. Period.

8 kommentarer:

mernen sa...
Den här kommentaren har tagits bort av skribenten.
mernen sa...

The use of "metaclass" is quite confusing indeed. Normally I call them singleton classes, since that's what most impls seem to use internally, but eigenclass is good too.

> You can define meta classes in Ruby if you want too by defining a subclass of Class.

Isn't that blocked? I mean, with a few hoops it's possible to allocate a subclass and even initialize it, but still it won't be instantiable.

From my understanding, Class is the metaclass in Ruby, and necessarily the only one. Or is there something I'm missing in the concept of metaclasses that require allowing you to define new metaclasses?

(Anyway, point taken and agreed: calling class << self the metaclass is erroneous and at times confusing)

Paul Barry sa...

Where are the terms meta class and eigen class defined?

Anonym sa...

Well... technically that is subjective still since an eigenclass can fill the role of a metaclass. That _does not_ make all eigenclasses metaclasses at all and it is an important mistake many make in their terminology (not accusing you of this).

So when is an eigenclass a metaclass? Like you said, one would have to subclass Class to create a metaclass. Class.new(Class) works in some implementations (MRI) but is still useless since it will fail to allocate objects from that. So how does one have a class that points back to Class as a superclass?

I am sure many already know the answer but to fill in the blanks we should inspect an eigenclass that fills the role of the so called metaclas:

meta = class << String; self end
meta.ancestors #=> [Class, Module, Object ...]

As we can see here, the eigenclass we extract here has ancestors that include Class which fulfills the role of metaclasses in other languages (providing things like class methods -- not the same as static methods).

Finally, in some ways, Class itself is a metaclass (as it is considered so in Smalltalk)... but this is more of a boring detail.

Reginald Braithwaite sa...

Thank you. I vastly prefer the term “eigenclass” to the alternatives “metaclass” or “singleton class.”

Eigenclasses are entirely unrelated to metaclasses in other OO languages like Smalltalk, so I find that confusing.

Anonym sa...

$ ruby -ve "p Class.new(Class).superclass"
ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]
Class
$ macruby -ve "p Class.new(Class).superclass"
MacRuby version 0.2 (ruby 1.9.0 2008-05-17) [universal-darwin9.0]
Class

mernen sa...

Brian, indeed, eigenclasses of classes are also technically metaclasses. Didn't think of that when writing my reply.

lrz: now try Class.new(Class).new :)

Anonym sa...

mernen,

Nail on the head. Eigenclasses of classes are Metaclasses. Their reason for existence is to define the behavior of another class. It's true that Ruby only allows one instance of them to exist (the one assigned to the class name constant), but I don't see how that makes them any less of a Metaclass. Certainly using the term Metaclass for classes defined to provide instance specific behavior to plain 'ol objects is a bad idea. I wrote up my own little glossary a little while back to suss out the terminology for myself.