Ruby Singleton Classes
Today I want to write something which so strange when first heard of while starting to learn Ruby programming: Singleton class. 1.What is Singleton Class Ruby provides a way to define methods that are specific to a particular object and such methods are known as Singleton Methods. When one ...
Today I want to write something which so strange when first heard of while starting to learn Ruby programming: Singleton class.
1.What is Singleton Class
Ruby provides a way to define methods that are specific to a particular object and such methods are known as Singleton Methods. When one declares a singleton method on an object, Ruby automatically creates a class to hold just the singleton methods. The newly created class is called Singleton Class.
Now, in Ruby, all objects have a class that it is an instance of. You can find this class by calling the method class on any object. The methods an object respond to will originally be the ones in that objects class.
To the Ruby interpreter, there is no difference in this case. Now, if foo is a String, the method bar will be available to call on the object referenced by foo, but not on any other Strings. The way this works is that the first time a method on a specific object is defined, a new, anonymous class will be inserted between the object and the real class. So, when I try to call a method on foo, the interpreter will first search inside the anonymous class for a definition, and then go on searching the real class hierarchy for an implementation. As you probably understand, that anonymous class is our singleton class.
2.Characteristics of Singleton Class
Ruby has singleton methods that function similarly to 'class' or 'static' methods in languages like Java, but the implementation is different. Ruby's 'class methods' are really just instance methods defined in the singleton class. Ruby doesn't have static methods like Java.
Only one object can be created
class Foo class << self def instance @instance ||= new end private :new end end # access the instance Foo.instance # => #<Singleton:0x007fd70c889880> # cannot instantiate Singleton.new # ~> -:12:in `<main>': private method `new' called for Singleton:Class (NoMethodError)
3.Ways to create Singleton Class
- ####Create methods with object.method
word = String.new def word.length "count what?" end word.length # => "count what?" word.class # => String another_word = String.new another_word.length # => 0 - ####Create methods from Module ```Ruby module Foo def foo "Module!" end end foo = "" foo.extend(Foo) foo.singleton_methods # => ["foo"]
-
Opening Singleton Class Directly
Anytime you see a strange looking class definition where the class keyword is followed by two less than symbols, you can be sure that a singleton class is being opened f or the object to the right of those symbols. In this example, the singleton class for the foobar object is being opened. As you probably already know, Ruby allows you to reopen a class at any point adding methods and doing anything you could have done in the original class definition. As with the rest of the examples in this section a foo method is being added to the foobar singleton class.
foobar = "" class << foobar def foo "Singleton class" end end foobar.singleton_methods # => [:foo]
- ####Evaluating Code in the context of Object
foo = "" foo.instance_eval <<EOT def foo "What is this?" end EOT foo.singleton_methods # => [:foo]
###4.Practical use of Singleton Class
I want also introduce the use of singleton module. A class mixing in the Singleton module is functionally equivalent to a class or module with 'class' methods and either a guaranteed initialization call or inline initialization. Compare this usage of Singleton:
require 'singleton' class Bar include Singleton attr_reader :count def initialize @count = 0 end def increase @count += 1 end end b1 = Bar.instance b1.increase b2 = Bar.instance b2.increase p b1.increase #=> 2 module Foo @count = 0 def self.increase @count *= 2 end def self.count @count end end Foo.increase Foo.increase p Foo.count #=> 2
In both cases you have a single global object that maintains state. (Because every constant you create in the global scope, including classes and modules, is a global object.)
The only functional difference is that with the Singleton you delay the initialization of the object until the first time you ask for it.
So, if you ever have 'class' methods on a class or module and you use those to change the state of that object (e.g. a class keeping track of all subclasses that inherit from it) you are essentially using a singleton.
###5.Conclusion
I hope you like this post and I welcome for any comments or questions to make this post better.