From: dblack@... Date: 2002-12-02T12:00:40+09:00 Subject: Re: class << self (was Re: [FAQ] What do some of Ruby's symbols mean?) Hi -- On Mon, 2 Dec 2002, Gavin Sinclair wrote: > From: "Martin DeMello" > > > or, if you are already *in* class Array and defining instance methods, > > you can highilght the fact that you're working in the same conceptual > > space by taking advantage of Ruby's setting 'self' to 'Array' when you say > > 'class Array', and writing > > > > class Array > > def instancemethod > > [define] > > end > > > > class << self > > def classmethod > > [define] > > end > > end > > end > > > > There's no arcane magic going on here - self is an object of class > > Class, and in this case it has the value Array. > > That, to me, is obfuscated. 'self' is generally understood as the current > instance of the class. Therefore, it is only meaningful inside instance > methods. In the "class << self" idiom, there is no instance method. 'self' > may be defined, but it's not *meaningful* in the sense described above. > There's a yawning gulf between syntax and semantics, and I suggest that it's > taking advantage of an undocumented feature. (Hmmm... none of this was undocumented last time I checked....) There's no necessary connection between self and being inside an instance method definition. I'm not sure where that idea came from, but it's not the case. There's always a 'self'. > My justification is that I have read a lot of Ruby documentation, and have > become proficient at the language, but the rationale for "class << self" has > never been impressed on me. In particular, the fact that 'self' has meaning > immediately inside a class definition has not been impressed on me. class << self is really not a special case though; it's just one use of the "class << object" idiom, so no separate syntax or design decision is involved. self is an object, and therefore it can occupy the 'object' slot in the idiom. As for what happens at the top level of a class definition: a class does have state, outside of its instance method definitions, and it is an object and has a singleton class (as well as a real class). So there has to be some way to get at those things. Actually... it's interesting to play around with other ways. For example: c = Class.new(Array) c.instance_eval { def class_talk puts "I'm a class: #{self}" end class_eval { def speak puts "I'm an instance of #{self.class}" end } } c.class_talk c.new.speak I find this useful in getting a slightly different view of what's going on with 'self' and class definitions. (In fact, I've heard a case made that the 'class' keyword should be done away with, in favor of the use of explicit Class instance constructors, but I'm not sure I'm aligned with that view :-) > That's why I wrote in an earier post that one shouldn't need to be > mindful of Ruby's metaclass model when performing the perfectly > normal OO practice of defining class (not instance) methods. The > means of doing that should be more intuitive. I've grown very skeptical of the notion of intuitiveness in computer programming languages :-) But anyway, I think that the most common syntax for class method definition (def MyClass.meth) allows for a nice clear syntax which also happens to take the form of just adding a method to an object's singleton class (but you don't have to worry about that level of it when writing the method). > Why would you say > class Array > class << self > ... > end > end > when you can say > class Array > class << Array > ... > end > end > ? Actually in that case I would just say: class << Array ... end and dispense with the surrounding class/end pair (unless there's something else going on there). If you do need the nesting, I personally find class << self to be slightly clearer, but it might depend on what else was interposed in the nesting. It's also slightly more maintainable, in the sense that if you change a class name, the 'self' reference updates itself automatically. David -- David Alan Black home: dblack@candle.superlink.net work: blackdav@shu.edu Web: http://pirate.shu.edu/~blackdav