From: Rick DeNatale Date: 2006-08-30T00:52:03+09:00 Subject: Singleton classes and methods (was Re: Reformat Ruby source code in vim?) On 8/28/06, James Edward Gray II wrote: > On Aug 28, 2006, at 12:26 PM, Robert Dober 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/