Hi –
From: “Martin DeMello” martindemello@yahoo.com
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
···
On Mon, 2 Dec 2002, Gavin Sinclair wrote:
–
David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav