What exactly is the singleton class in ruby?
Asked Answered
S

5

94

Is the singleton class in Ruby a class in and of itself? Is it the reason why all objects belong to "class?" The concept is fuzzy, but I believe it has something to do with why I can define a class method at all (class foo; def foo.bar ...).

What is the singleton class in Ruby?

Supportable answered 17/10, 2008 at 14:35 Comment(0)
L
166

First, a little definition: a singleton method is a method that is defined only for a single object. Example:

irb(main):001:0> class Foo; def method1; puts 1; end; end
=> nil
irb(main):002:0> foo = Foo.new
=> #<Foo:0xb79fa724>
irb(main):003:0> def foo.method2; puts 2; end
=> nil
irb(main):004:0> foo.method1
1
=> nil
irb(main):005:0> foo.method2
2
=> nil
irb(main):006:0> other_foo = Foo.new
=> #<Foo:0xb79f0ef4>
irb(main):007:0> other_foo.method1
1
=> nil
irb(main):008:0> other_foo.method2
NoMethodError: undefined method `method2' for #<Foo:0xb79f0ef4>
        from (irb):8

Instance methods are methods of a class (i.e. defined in the class's definition). Class methods are singleton methods on the Class instance of a class -- they are not defined in the class's definition. Instead, they are defined on the singleton class of the object.

irb(main):009:0> Foo.method_defined? :method1
=> true
irb(main):010:0> Foo.method_defined? :method2
=> false

You open the singleton class of an object with the syntax class << obj. Here, we see that this singleton class is where the singleton methods are defined:

irb(main):012:0> singleton_class = ( class << foo; self; end )
=> #<Class:#<Foo:0xb79fa724>>
irb(main):013:0> singleton_class.method_defined? :method1
=> true
irb(main):014:0> singleton_class.method_defined? :method2
=> true
irb(main):015:0> other_singleton_class = ( class << other_foo; self; end )
=> #<Class:#<Foo:0xb79f0ef4>>
irb(main):016:0> other_singleton_class.method_defined? :method1
=> true
irb(main):017:0> other_singleton_class.method_defined? :method2
=> false

So an alternative means of adding singleton methods to an object would be to define them with the object's singleton class open:

irb(main):018:0> class << foo; def method3; puts 3; end; end
=> nil
irb(main):019:0> foo.method3
3
=> nil
irb(main):022:0> Foo.method_defined? :method3
=> false

In summary:

  • methods must always belong to a class (or: be instance methods of some class)
  • normal methods belong to the class they're defined in (i.e. are instance methods of the class)
  • class methods are just singleton methods of a Class
  • singleton methods of an object are not instance methods of the class of the object; rather, they are instance methods of the singleton class of the object.
Loudspeaker answered 17/10, 2008 at 18:1 Comment(2)
On my Headstone it will say "RIP Ruby Singleton. Pistos saved my sanity."Cere
@sawa I appreciate the intent of your edits, but I feel that they change the meaning and communication of my post a little too much, so I have rolled your edits back.Loudspeaker
A
36

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.


    foo = Array.new
    def foo.size
      "Hello World!"
    end
    foo.size  # => "Hello World!"
    foo.class # => Array
    #Create another instance of Array Class and call size method on it
    bar = Array.new
    bar.size  # => 0
Singleton class is object specific anonymous class that is automatically created and inserted into the inheritance hierarchy.

singleton_methods can be called on an object to get the list of of names for all of the singleton methods on an object.

    foo.singleton_methods  # => [:size]
    bar.singleton_methods  # => []

This article really helped me to understand Singleton Classes in Ruby and it has a good code example.

Alignment answered 19/1, 2012 at 20:21 Comment(4)
While this answer is over a year old and the link is helpful it would be better if you post the essential parts of the answer here, on this site, or your post risks being deleted See the FAQ where it mentions answers that are 'barely more than a link'. You may still include the link if you wish, but only as a 'reference'. The answer should stand on its own without needing the link.Gilead
agree with @bluefeet hereBock
Thanks @bluefeet, updated the answer to address your comment.Alignment
This is the clearest answerEremite
B
7

As just update to @Pistos answer, from version 1.9.2 ruby add new syntax to getting singleton class

 singleton_class = ( class << foo; self; end )

can be replaced with:

singleton_class = foo.singleton_class

https://apidock.com/ruby/Object/singleton_class

Bowerman answered 24/10, 2017 at 17:42 Comment(0)
R
3

The most pragmatic/action-oreinted way to think of it (IMHO) is: as an inheritance chain, or method lookup/resolution order. This picture might help

http://www.klankboomklang.com/2007/11/25/modules-part-i-enter-the-include-class/

This is r 1.9, contrasting builtin and user-defined classes: i'm still digesting this one.

http://d.hatena.ne.jp/sumim/20080111/p1

Also, i htink a confusing use of the term is "Singleton object", which is different concept. A singleton object comes from a class which has its constructor/instantiator method overridden so that you can allocate only one of that class.

Rockery answered 17/10, 2008 at 16:49 Comment(1)
One of the links is dead. And the other is Japanese!Terefah
E
3

A singleton class in the simplest terms is a special class ruby whips up to host methods defined on individual objects. In ruby, it is possible to define methods on individual objects that are unique to that object alone. For instance consider the following below

class User; end
user = User.new
def user.age
  "i'm a unique method"
end
user1 = User.new 
user.age #"i'm a unique method"
user1.age # NoMethodError (undefined method `age' for #<User:0x0000559c66ab7338>)

As you can see above, user1 object does not respond to the 'age' method because it is a singleton method, a method uniquely defined on user object. For this to happen, ruby creates a special class, called singleton class, or eigenclass, to host this unique method. You can verify this by doing the following:

user.singleton_class # #<Class:#<User:0x0000559c66b47c58>>

You can also ask ruby whether the 'age' method is found here by using the method object to find out where the method 'age' is defined. When you do this you will see that singleton class has that method.

user_singleton_class = user.method(:age).owner # #<Class:#<User:0x0000559c66b47c58>>
user.method(:age).owner == user.singleton_class # true
user_singleton_class.instance_methods(false) # [:age]

Also note that, as far a singleton class goes, singleton methods are actually it's instance methods.

user.singleton_methods == user_singleton_class.instance_methods(false) # true
Eldreeda answered 29/2, 2020 at 18:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.