What exactly is the singleton class in ruby?
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.
What is a singleton class in Ruby?
Singleton classes hold methods that are specific to a single object.
For generic objects, it's a nice-to-have feature. But for classes, it's crucial. Let's start with the objects:
Singleton classes for objects
Instance methods are usually defined in classes. All instances of the same class share the same instance methods. The singleton class sits between the object and its class. It allows each instance to have its own set of methods, independent of the other instances.
If we have two classes, Foo
and Bar
with 2 instances each a
, b
and c
, d
:
class Foo ; end
class Bar ; end
a = Foo.new #=> #<Foo:0x00007fc280963008>
b = Foo.new #=> #<Foo:0x00007f8319016b18>
c = Bar.new #=> #<Bar:0x00007fa66c8d7290>
d = Bar.new #=> #<Bar:0x00007f94d5106ac8>
You would have this class structure: (simplified, excluding modules)
object singleton class class superclass ...
a ── #<Class:#<Foo:0x00007fc280963008>> ─┐
├─ Foo ─┐
b ── #<Class:#<Foo:0x00007f8319016b18>> ─┘ │
├─ Object ── BasicObject
c ── #<Class:#<Bar:0x00007fa66c8d7290>> ─┐ │
├─ Bar ─┘
d ── #<Class:#<Bar:0x00007f94d5106ac8>> ─┘
Ruby creates those singleton classes lazily, for example when calling singleton_class
.
So when defining a method a.hello
, it is not stored in a
's class Foo
, but in a
's singleton class:
def a.hello
'hello from a'
end
a.method(:hello).owner
#=> #<Class:#<Foo:0x00007fc280963008>> <-- a's singleton class
Because of that, b
doesn't see that method, even though both are Foo
instances:
b.hello #=> NoMethodError: undefined method `hello'
And we can even define a method with the same name for b
without interfering with a
:
def b.hello
'hello from b'
end
b.method(:hello).owner
#=> #<Class:#<Foo:0x00007f8319016b18>> <-- b's singleton class
a.hello #=> "hello from a"
b.hello #=> "hello from b"
We could also define a generic hello
in Foo
and override it on a per instance level: (you usually don't do that, but it's possible)
class Foo
def hello
'hello'
end
end
def a.hello
"#{super} from a"
end
def b.hello
"b says #{super.upcase}!"
end
a.hello #=> "hello from a"
b.hello #=> "b says HELLO!"
c = Foo.new
c.hello #=> "hello"
Singleton classes for classes
The above is especially important for classes. Each class is an instance of Class
:
Foo.class #=> Class
Let's say we wanted to have a method Foo.hello
, where would we define it?
Instance methods are usually defined in the instance's class, so we could define it in Foo
's class:
class Class
def hello
'Hello from Foo'
end
end
Foo.hello
#=> "Hello from Foo"
But that would make the method available to all instances of Class
:
Bar.hello
#=> "Hello from Foo"
String.hello
#=> "Hello from Foo"
It would be better to have a place that's exclusive to the Foo
instance. And that place is Foo
's singleton class:
def Foo.hello
'Hello from Foo'
end
or
class Foo
def self.hello # <-- self is Foo, so this is just "def Foo.hello"
'hello from Foo'
end
end
Just like a.hello
above, this method is only available to Foo
:
Foo.hello #=> "hello from Foo"
Bar.hello #=> NoMethodError
We call these methods class methods, but they are really just instance methods of the singleton class:
Foo.method(:hello).owner
#=> #<Class:Foo> <-- Foo's singleton class
Foo.method(:hello).unbind == Foo.singleton_class.instance_method(:hello)
#=> true
And if you compare the singleton methods for classes with those for objects, you'll see that they are identical. That's because in Ruby, classes are objects too, and all objects work alike.
What exactly is the singleton class in ruby?
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.
Singleton method vs. class method
Most of what happens in Ruby involves classes and modules, containing
definitions of instance methods
class C
def talk
puts "Hi!"
end
end
c = C.new
c.talk
Output: Hi!
But as you saw earlier (even earlier than you saw instance methods inside classes), you can also define singleton methods directly on individual objects:
obj = Object.new
def obj.talk
puts "Hi!"
end
obj.talk
#Output: Hi!
When you define a singleton method on a given object, only that object can call that method. As you’ve seen, the most common type of singleton method is the class method—a method added to a Class object on an individual basis:
class Car
def self.makes
%w{ Honda Ford Toyota Chevrolet Volvo }
end
end
But any object can have singleton methods added to it. The ability to define method- driven behavior on a per-object basis is one of the hallmarks of Ruby’s design.
Singleton classes
Singleton classes are anonymous: although they’re class objects (instances of the class Class ), they spring up automatically without being given a name. Nonetheless, you can open the class-definition body of a singleton class and add instance methods, class methods, and constants to it, as you would with a regular class.
Note:
Every object has two classes:
■ The class of which it’s an instance
■ Its singleton class
----------------------------------------------------------------
At Last I would highly recommends you to watch.
1: The Ruby Object Model and Metaprogramming For detail info about singleton method vs. class method ruby
2: MetaProgramming - Extending Ruby for Fun and Profit - by Dave Thomas
Hope this help you!!!
When is it wise to use Singleton classes in Ruby?
Note that 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 :jam
def initialize
@jam = 42
end
def double
@jam *= 2
end
end
b1 = Bar.instance
b1.double
b2 = Bar.instance
b2.double
p b1.jam #=> 168
with this no-magic module:
module Foo
@jam = 42
def self.double
@jam *= 2
end
def self.jam
@jam
end
end
Foo.double
Foo.double
p Foo.jam #=> 168
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.
What's the difference between a class and the singleton of that class in Ruby?
To answer your question directly: Module#define_method
creates an instance method. A "class method" is an instance method on the singleton class (or eigenclass) of a Class
object. I'm sure that sounds very confusing. Let me explain why Ruby includes the concept of "singleton classes" in the first place:
First, let me say that the basic "framework" of different object-oriented languages are quite varied. Ruby's design as regards objects, classes, metaclasses, etc. is by no means the only possible one, and the language could have been designed in a different way. Having said that, there are logical reasons why Ruby works the way it does. I'll try to explain as concisely as possible...
Think of a simple method call, like:
[1,2,3].first
Here we are calling a method called first
, with an Array
object as receiver. To process this method call, Ruby needs to search for a matching method definition, and execute it. Where does it start looking? Naturally, in the instance methods of Array
. If it doesn't find it there, it will look in Array
's superclass, then the superclass of the superclass, as well as Module
s which are mixed into Array
or its superclasses, etc.
"Class-based" (as opposed to prototype-based) object-oriented languages all work this way, more or less. If you've ever programmed in Java, or C++, or Python, this behavior should be familiar to you.
Now, the creator of Ruby wanted to also make it possible to add methods to just one object. In a prototype-based OO language, that would be easy, but how could it work in a class-based language? He made it possible by introducing the idea of "singleton classes" or "eigenclasses".
A "singleton class" is, simply, a class which has only one instance. I believe that rather than trying to keep track of a different singleton class for every single object, Ruby waits until the first time you try to access an object's singleton class, and then creates the class and inserts it into the object's inheritance chain dynamically.
As I just said, when a method is called, Ruby looks first in the object's class to find a matching definition, then the superclass, etc. Since singleton classes are inserted as the first link in an object's inheritance chain, they are the first place which Ruby will look for a method definition.
Bringing in the concept of "singleton classes" also solved another problem at the same time. In Java (for example), you can define static
methods which are called on a class. In Ruby, people often want to do something similar. With "singleton" classes and methods, you can do just that: all you have to do is define a singleton method on a Class object.
(Remember that classes are also objects in Ruby. That's why the concept of "singleton" classes and methods can "kill 2 birds with 1 stone", as I explain above!)
EXTRA INFORMATION:
At the beginning, I mentioned "instance methods". I don't know if that might be confusing, or if you already know what "instance methods" are. When you define a Ruby class, like this...
class MyClass
def my_method
# do something
end
end
...then my_method
will be added as an instance method of MyClass
. When Ruby searches an object's class, superclass, etc. for a method definition, what it actually looks at are their instance methods. So an object's "methods" are the instance methods of its class, plus the instance methods of the superclass, the superclass of the superclass, etc.
About how singleton classes interact with method lookup in Ruby, there is a slight inconsistency which I didn't mention above. If you want to understand in detail:
Singleton classes of class objects are treated a little differently from singleton classes of other objects in general. If you have a class A
which inherits from another class B
, and B
has singleton methods, A
will inherit not just the instance methods, but also the singleton methods of B
. In other words, B
's singleton class is treated as a superclass of A
's singleton class. This is not true of the singleton classes of any other objects.
Ruby: Are singleton classes really own anonymous classes?
str = "a string" # => "a string"
[str, str.object_id] # => ["a string", 47279316765840]
[str.class, str.class.object_id] # => [String, 47279301115420]
def str.greet
"hello"
end # => :greet
str.greet # => "hello"
Ruby hides the eigenclass when you ask str.class
or look the ancestory chain (str.class.ancestors
). You can however get the reference to eigenclass by returning self after inspecting in it's class using <<
str_class = class << str
self
end
# => #<Class:#<String:0x007fbba28b3f20>>
str_class.instance_methods(false) #=> [:greet] # the singleton method you defined becomes the instance method of this eigenclass. :)
str_class.ancestors
[#<Class:#<String:0x007fbba28b3f20>>, String, Comparable, Object, Kernel, BasicObject]
Ruby Singleton, module vs class
The simplest way to get an object in Ruby is to use, well, an object:
class << Foo = Object.new
attr_accessor :foo
end
Using either a module or a class is overkill, both have features you don't need.
Related Topics
Code Block Passed to Each Works With Brackets But Not With 'Do'-'End' (Ruby)
Eventsource/Server-Sent Events Through Nginx
How to Replace Accented Latin Characters in Ruby
What Does @@Variable Mean in Ruby
In Rails, How to Render Json Using a View
Difference Between Datetime and Time in Ruby
How to Have Ruby Logger Log Output to Stdout as Well as File
Should Gemfile.Lock Be Included in .Gitignore
How to Sum Array of Numbers in Ruby
How to Avoid Running Activerecord Callbacks
What's the Difference Between Uri.Escape and Cgi.Escape
How Does Instance_Eval Work and Why Does Dhh Hate It
Rails Has_Many :Through Find by Extra Attributes in Join Model