Hi --
Now I actually have the inverse problem. The good news is the code
works perfectly -- thank you, by the way -- but the bad news is I
don't totally know why.
Ah, ok. The class object creates a singleton, which is where all the
method definitions live?
All the singleton method definitions of that class object, yes. It's
really just a not-very-special case of the general principle that an
object's singleton methods live in the object's singleton class.
It's perhaps easier to see the workings of it when the object isn't a
class:
str = "I am a string
class << str
def just_for_me
puts "This method is just for me!"
end
end
I've defined a singleton method on the one String object, str. No
other string will have that method. If I'd defined it in String, they
would. But I've defined it in str's singleton class (class << str),
so only str will have it:
str.just_for_me # This method is just for me!
"other".just_for_me # NoMethodError
Now, watch as I take that example -- and the explanation -- and
substitute a Class object for the String object:
class Thing; end
class << Thing
def just_for_me
puts "This method is just for me!
end
end
I've defined a singleton method on the one Class object, Thing. No
other class will have that method. If I'd defined it in Class, they
would. But I've defined it in Thing's singleton class (class <<
Thing), so only Thing will have it:
Thing.just_for_me # This method is just for me!
Array.just_for_me # NoMethodError
Note that in the Thing example, just_for_me is what we would call a
"class method". A class method, then, is just a singleton method
defined for a class object.
And this is because the class, having been defined, now has a
singleton containing all its methods, and we don't want to create a
new patch, we just want to append new methods to the existing
singleton?
Yes, we want to define methods inside the singleton class of Thing.
The singleton class of Thing is not actually created until we ask to
get inside it, but that's really an implementation detail.
I think I do get it, although I admit I'm still puzzled on the
singleton class / birth class thing.
It's nature vs. nurture. Every object comes into existence with
certain capabilities -- that is, when you send it messages, it
searches through specific classes and modules, in a specific order,
looking for corresponding methods. From that perspective, all
instances of a given class are the same as each other.
But you can also add capabilities to an object. An object that is
"born" ignorant of a certain message need not remain that way. You
can do this by adding to the object's class -- if you want *all*
instances of that class to have the new capability. Or, if you just
want one object to have it, you can add a method to that object's
singleton class.
So by its nature, a String instance can do certain things:
str = "hello there"
str.split(/ll/)
str.upcase
str.reverse
etc. By way of nurture, we can add to this string by adding to all
strings:
class String
def new_method
...
end
end
or by adding a method to this one string's singleton class, as in the
examples above.
(You can, by the way, also insert a method into an object's singleton
class with the "def" keyword, like this:
def str.new_method
...
end
or
def Thing.some_class_method
...
end
)
The main thing going on in all this is that Ruby objects can change
over the course of their lives. That's the principle being enforced;
and singleton classes are just the way Matz has chosen to bring that
principle to life.
I get a lot of mileage out of thinking of the method look-up path.
When you send a message to an object, it walks the path -- a
succession of classes and modules, like rooms strung along a corridor
-- and looks for the method. First, it checks in its own singleton
class (if you've created one), and in any modules mixed in to the
singleton class. If no method with the right name is found, it
proceeds to its "birth" class, and then to the modules mixed in there.
And so on -- until it gets to Object, and the module that's mixed in
*there* (Kernel). Then, if it still hasn't found the method, it gives
up.
This post could probably do with some more editing but I don't have it
in me right now
I hope it's helpful. You might also have a look
at a little essay that covers similar material:
http://www.wobblini.net/singletons.html. (And my book, of course
David
--
Q. What's a good holiday present for the serious Rails developer?
A. RUBY FOR RAILS by David A. Black (
http://www.manning.com/black)
aka The Ruby book for Rails developers!
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (
http://www.rubypal.com)