On Sat, May 16, 2009 at 1:24 AM, Gary Wright <gwtmp01 / mac.com> wrote: > > On May 15, 2009, at 7:46 AM, Joshua Ballanco wrote: >>> >>> Right. So then the question: is there a compelling reason that they >>> should be allowed to be subclassed? (I mean, other than the obvious: >>> "Because that's not the way Ruby was designed" answer.) I cannot come up >>> with any compelling technical reason why the artificial limitation of being >>> unable to subclass "virtual classes"[1] should exist. > > The purpose of an eigenclass is to hold per object methods. ¨Βσυγθτθες> is always always a one-to-one relationship between an eigenclass and its > "eigeninstance" (sorry, but I can't think of a clearer term at the moment). > > The idea of subclassing an eigenclass contradicts that one-to-one > relationship. ¨Βωογουμσυβγμασσ αξ ειηεξγμασστθεςχουμβε ξο χατο > cause ruby to search the new subclass for instance methods since it wouldn't > have a matching eigeninstance (sorry, again). ¨Βχουμξοβε ιξ τθνετθοδ > lookup chain of any object. > > Just to be complete, I'll point out that there is a way for eigenclasses to > have a subclass and that is when the eigeninstances are themselves classes. > ¨Βθιισ νοστ γμεαιξ ±®Ή® ¨Βισ συβγμασσ οζ Α¬ τθεξ Β®ειηεξγμασσ χιμμ > be a subclass of A.eigenclass. ¨Βφειξ τθισ γασε αξθαφε το εψισ> before their eigenclasses can be accessed and not the other way around. And there, IMHO, is where things break down. If the definition of an eigenclass is a 'class' which holds per object methods, then the class of a class which has subclasses is not an eigenclass since it provides methods not only to it's sole instance but also to it's instance's subclass(es). That's why I prefer to think of the objects which serve as the class of a class as metaclasses, which is in line with the terminology used in several other languages. This whole area of Ruby reminds me a bit of Plato's cave, we see images on the wall cast by "smoke" and "mirrors" in the implementation, and try to name them. And the smoke has been shifting a bit and the mirrors have been moving slightly. When you step outside of the cave and look at the implementation you find: There's a flag called FL_SINGLETON which when set in the header of a class object means: * It will get cloned if you clone its instance * You can't copy it. * You can't make a subclass of it, unless you are ruby itself creating a subclass in which case subclasses of the "singleton" metaclass are created under the covers. * It will be bypassed by the Object#class method * It will be filtered out of the results Module#ancestors method * It will be skipped in the search for methods by Module#instance_methods and it's related methods * Its methods are considered singleton methods * It has a hidden 'class' instance variable __attached__ which points to it's sole instance * Its skipped over by ObjectSpace.each_object, so ObjectSpace.each_object(Class) won't yield it. * It will prevent dumping by Marshall.dump So what exactly does the singleton in FL_SINGLETON mean. Well, it does mean that a class marked with FL_SINGLETON has only one direct instance. It doesn't mean in the case of a singleton class which happens to be a metaclass that it doesn't have subclasses, just that you as a Ruby programmer can only create or add to its subclasses by subclassing its attached class. And while you might think that singleton method was a synonym for instance specific method, once again this is only true when it's a singleton method within an instance-specific singleton class. class Foo def self.blat :blat end end class Bar < Foo end Foo.singleton_methods => [:blat] Bar.singleton_methods => [:blat] The 2nd ed of the Pickaxe used the term "virtual class" and seems to call the FL_SINGLETON bit the 'V' bit. Looking at Ruby 1.8.6, the term virtual class only appears in errors raised when you try to 1. Try to make a subclass of a class marked with FL_SINGLETON and you'll get the error "can't make subclass of virtual class" 2. Try to add a singleton method to an instance of an immediate class (e.g. a Fixnum), since there's no klass ptr so nowhere to insert the needed instance specific class in the lookup chain, and you'll get the error "no virtual class for %s" 3. Try to instantiate an instance of a class marked with FL_SINGLETON and you'll get the error can't create instance of virtual class" And in Ruby 1.9, these error descriptions have all be changed to remove the usage of "virtual class" and replace it with "singleton class". I kind of wish that FL_SINGLETON had actually been named FL_VIRTUAL, or FL_HIDDEN, since what the flag does mostly is to hide such classes in the standard library provided API. (ignoring the leak from class < a;self;end Back in the mists of Ruby history, it became popular to call any class marked with FL_SINGLETON as a metaclass, probably because that's what _why named the leak method in the Poignant Guide. That added another layer of confusion, because to many of us metaclass means the class of a class, and an instance-specific class ain't a metaclass, it's a class whether it's hidden or not. And I think that that's where the name eigenclass got coined, as an alternative to singleton class, for better or worse. And with the publication of "The Ruby Programming Language" it's gotten a bit of a blessing from Matz, although the Ruby 1.9 implementation uses singleton class in those errors where virtual class was used before. I personally think that the distinction between metaclasses (in the generally accepted sense of the class of a class) and instance-specific classes is more important than the accidental similarities between singleton classes used as instance-specific classes and singleton-classes used as metaclasses. And I guess eigenclass is not a bad term to use for a class which provides behavior to a single instance, i.e. an instance-specific class, but I don't like it as a term for a metaclass. But that's just me, after all it's all just images caused by smoke and mirrors <G> -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale