On 8/28/06, James Edward G. II [email protected] wrote:
On Aug 28, 2006, at 12:26 PM, Robert D. wrote:
Not at all. That’s why I said “singleton class” in the first place.
Hey man, all this singleton class stuff is just finally starting to
sink into my brain, don’t set me back on the path to enlightenment!
Singleton classes are a slippery concept, and singleton methods even
more so. IMHO, the terminology comes from a bit of the
implementation. I’ve been slogging through the 1.8 implementation in
order to understand what’s really going on. Just what is the
definition of a singleton class, or a singleton method?
In the 1.8 implementation, a singleton class seems to be a class which
has a flag bit called FL_SINGLETON set in its object header. This
appears to be the ‘virtual’ bit alluded to in Chapter 24 of the
pickaxe 2nd ed. There really isn’t a flag named FL_VIRTUAL or
anything like that, but there are a couple of places where the
FL_SINGLETON bit is checked and an exception is raised with a message
of the form, “you can’t do that with a virtual class”.
If a singleton class is a class which is tied to one and only one
object, then a singleton method should be a method tied to one and
only one object as well, but check this out:
class X
def foo;end
end
X.singleton_methods => [“foo”]
class Y < X; end
Y.singleton_methods => [“foo”]
Does anyone beside me find that surprising? Now the rdoc of
Object#singleton_methods says that it takes an optional boolean
argument which if false will include methods in modules included in
obj.
Y.singleton_methods(false) => []
So does Y include X?
Y.include? X
TypeError: wrong argument type Class (expected Module)
from (irb):29:in `include?’
from (irb):29
By the way, another piece of the 1.8 implementation is the type field
in the object header, this is actually the low-order 4 bits of the
flag field, and it’s used as kind of a union discriminator to indicate
which of several C structs map the remainder of the object’s ‘box.’
One of the type codes is T_ICLASS which is a pseudo-type, which means
that the object looks like a class, but it’s actually a proxy for a
module included in the class.
Actually, unlike singleton classes of instances, which can’t have
subclasses, singleton classes of classes can, and will if the class
which owns one has a subclass itself.
Looking at the code which implements singleton_methods it creates an
empty array, and then looks to see if the class of self is flagged as
a singleton, and if so adds the method names from its method table to
the array. Then, if the argument is true, it walks up the superclass
chain while the class it’s looking at is either marked with
FL_SINGLETON or has a type of T_ICLASS, and adds those methods.
So the operational definition of a singleton methods seems to be a
method of an object which appears in a singleton class or a module
mixed directly INTO a singleton class, or comes from a singleton class
which is in the superclass chain of the objects class BEFORE a non
singleton class, or a module directly mixed into one of those
singleton classes. Whew.
Note that in the paragraph above, ‘singleton class’ means a class
whose FL_SINGLETON flag bit is set. Which I guess IS the definition
of a singleton class.
It might just be me, but I find the use of singleton class both to
provide instance behaviour, and to serve the purpose of a metaclass a
liitle too much the product of the implementation, leading to
confusion.
To my mind, the name singleton class implies that it should provide
methods to a single instance. Singleton classes of classes don’t do
this. Normally singleton classes refuse to be subclassed, but
singleton classes of classes get subclassed ‘under the covers’ when
their class gets subclassed.
The code which implements singleton_methods seems to be trying to
produce a list of methods which are available only to the instance
associated with a singleton class, but this breaks down for singleton
classes of classes since it also lists inherited ‘singleton’ methods,
which since there’s no real distinction that I can see between
singleton methods of a class and class methods, means that it lists
all inherited class methods of a class. Perhaps it’s just a bug and
the singleton_classes implementation should only look at T_ICLASSes
after the initial singleton class.
It appears that a lot of the reason for FL_SINGLETON and T_ICLASS is
to hide a slightly tricky implementation from showing through some of
the reflection methods. Perhaps Ruby would be a little cleaner if it
just called a metaclass a metaclass, and a singleton class a singleton
class, and reserved the later for a class providing behavior for a
single instance. But that’s just my opinion and it’s not the way
things are.
I just realized that there’s no class_methods family of methods in
Ruby. I can’t say:
Array.class_methods
instead I have to say:
Array.singleton_methods
While I can say
Array.private_instance_methods
How do I get the private_class_methods?
Well, such musings are probably a bit like arguing about how many
angels can dance on the head of a pin, but I hope someone else finds
them interesting.
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/