Singleton Class
Inheritance of Singleton Class
Section titled “Inheritance of Singleton Class”Subclassing also Subclasses Singleton Class
Section titled “Subclassing also Subclasses Singleton Class”class Exampleend
Example.singleton_class #=> #<Class:Example>
def Example.foo :exampleend
class SubExample < Exampleend
SubExample.foo #=> :example
SubExample.singleton_class.superclass #=> #<Class:Example>Extending or Including a Module does not Extend Singleton Class
Section titled “Extending or Including a Module does not Extend Singleton Class”module ExampleModuleend
def ExampleModule.foo :fooend
class Example extend ExampleModule include ExampleModuleend
Example.foo #=> NoMethodError: undefined methodSingleton classes
Section titled “Singleton classes”All objects are instances of a class. However, that is not the whole truth. In Ruby, every object also has a somewhat hidden singleton class.
This is what allows methods to be defined on individual objects. The singleton class sits between the object itself and its actual class, so all methods defined on it are available for that object, and that object only.
object = Object.new
def object.exclusive_method 'Only this object will respond to this method'end
object.exclusive_method# => "Only this object will respond to this method"
Object.new.exclusive_method rescue $!# => #<NoMethodError: undefined method `exclusive_method' for #<Object:0xa17b77c>>The example above could have been written using define_singleton_method:
object.define_singleton_method :exclusive_method do "The method is actually defined in the object's singleton class"endWhich is the same as defining the method on object’s singleton_class:
# send is used because define_method is privateobject.singleton_class.send :define_method, :exclusive_method do "Now we're defining an instance method directly on the singleton class"endBefore the existence of singleton_class as part of Ruby’s core API, singleton classes were known as metaclasses and could be accessed via the following idiom:
class << object self # refers to object's singleton_classendIntroduction
Section titled “Introduction”Ruby has three types of objects:
- Classes and modules which are instances of class Class or class Module.
- Instances of classes.
- Singleton Classes.
Each object has a class which contains its methods:
class Exampleend
object = Example.new
object.class # => ExampleExample.class # => ClassClass.class # => ClassObjects themselves can’t contain methods, only their class can. But with singleton classes, it is possible to add methods to any object including other singleton classes.
def object.foo :fooendobject.foo #=> :foofoo is defined on singleton class of object. Other Example instances can not reply to foo.
Ruby creates singleton classes on demand. Accessing them or adding methods to them forces Ruby to create them.
Accessing Singleton Class
Section titled “Accessing Singleton Class”There are two ways to get singleton class of an object
singleton_classmethod.- Reopening singleton class of an object and returning
self.
object.singleton_classsingleton_class = class << object selfendAccessing Instance/Class Variables in Singleton Classes
Section titled “Accessing Instance/Class Variables in Singleton Classes”Singleton classes share their instance/class variables with their object.
class Example @@foo = :exampleend
def Example.foo class_variable_get :@@fooend
Example.foo #=> :exampleclass Example def initialize @foo = 1 end
def foo @foo endend
e = Example.new
e.instance_eval <<-BLOCK def self.increase_foo @foo += 1 endBLOCK
e.increase_fooe.foo #=> 2Blocks close around their instance/class variables target. Accessing instance or class variables using a block in class_eval or instance_eval isn’t possible. Passing a string to class_eval or using class_variable_get works around the problem.
class Foo @@foo = :fooend
class Example @@foo = :example
Foo.define_singleton_method :foo do @@foo endend
Foo.foo #=> :exampleMessage Propagation with Singleton Class
Section titled “Message Propagation with Singleton Class”Instances never contain a method they only carry data. However we can define a singleton class for any object including an instance of a class.
When a message is passed to an object (method is called) Ruby first checks if a singleton class is defined for that object and if it can reply to that message otherwise Ruby checks instance’s class’ ancestors chain and walks up on that.
class Example def foo :example endend
Example.new.foo #=> :example
module PrependedModule def foo :prepend endend
class Example prepend PrependedModuleend
Example.ancestors #=> [Prepended, Example, Object, Kernel, BasicObject]e = Example.newe.foo #=> :prepended
def e.foo :singletonend
e.foo #=> :singletonReopening (monkey patching) Singleton Classes
Section titled “Reopening (monkey patching) Singleton Classes”There are three ways to reopen a Singleton Class
- Using
class_evalon a singleton class. - Using
class <<block. - Using
defto define a method on the object’s singleton class directly
class Exampleend
Example.singleton_class.class_eval do def foo :foo endend
Example.foo #=> :fooclass Exampleend
class << Example def bar :bar endend
Example.bar #=> :barclass Exampleend
def Example.baz :bazend
Example.baz #=> :bazEvery object has a singleton class which you can access
class Exampleendex1 = Example.newdef ex1.foobar :foobarendex1.foobar #=> :foobar
ex2 = Example.newex2.foobar #=> NoMethodErrorSyntax
Section titled “Syntax”- singleton_class = class << object; self end
Remarks
Section titled “Remarks”Singleton classes only have one instance: their corresponding object. This can be verified by querying Ruby’s ObjectSpace:
instances = ObjectSpace.each_object object.singleton_class
instances.count # => 1instances.include? object # => trueUsing <, they can also be verified to be subclasses of the object’s actual class:
object.singleton_class < object.class # => trueReferences: