A singleton method is a method that belongs to a single object. A singleton class, on the other hand, is a class that defines a single object. Confused? Me too. Let’s take a closer look.
Let’s suppose you create a few dozen objects, each of which is an instance of the Object class. Naturally they all have access to inherited methods such as inspect
and class
. But now you decide that you want just one special object (for the sake of variety, let’s call him ob
), which has one special method (let’s call it blather
).
You don’t want to define a whole new class for this one object since you will never again create any more objects with the blather
method. So, you create a class especially for little ob
.
You don’t need to name this class. You just tell it to attach itself to ob
by putting a <<
between the keyword class
and the name of the object. Then you add code to the class in the usual way:
singleton_class.rb
ob = Object.new # singleton class class << ob def blather( aStr ) puts("blather, blather #{aStr}") end end
Now ob
, and only ob
, has not only all the usual methods of the Object class; it also has the methods (here just the blather
method, but there could, in principle, be many more) of its own special anonymous class:
ob.blather( "weeble" ) #=> "blather, blather weeble"
If you’ve been paying close attention, you might have noticed that the singleton class seems to be doing something rather similar to a singleton method. With a singleton class, I can create an object and then add extra methods packaged up inside an anonymous class. With singleton methods, I can create an object and then add methods one by one:
singleton_class2.rb
ob2 = Object.new def ob2.blather( aStr ) # <= this is a singleton method puts( "grippity, grippity #{aStr}" ) end ob2.blather( "ping!" ) #=> grippity, grippity ping!
Similarly, I could rewrite the “star prize” program. In the previous version I added a singleton method, congratulate
, to an object named starprize
. I could just as easily have created a singleton class containing the congratulate
method:
starprize = MyClass.new( "Star Prize" ) class << starprize def congratulate puts( "You've won a fabulous holiday in Grimsby!" ) end end
In fact, the similarity is more than skin deep. The end result of the previous code is that congratulate
becomes a singleton method of starprize
. I can verify this by checking whether the array of singleton methods available for the item
object contains the name congratulate
:
if item.singleton_methods.include?(:congratulate) # Ruby 1.9
In Ruby 1.9, the singleton_methods
method returns an array of symbols representing the method names. This is why I have used the symbol :congratulate
in the previous code. However, in Ruby 1.8, singleton_methods
returns an array of strings. So, if you are using Ruby 1.8, you should be sure to use the following test using the string argument "congratulate"
:
if item.singleton_methods.include?("congratulate") # Ruby 1.8
What’s the difference between a singleton method and a singleton class? The short answer is, not a lot. These two syntaxes provide different ways of adding methods to a specific object rather than building those methods into its defining class.