Ruby Singleton methods for class and objects
First of all, the way to list singleton methods is with singleton_methods
. The methods
method returns a list of the names of public and protected methods of the object. Also, it is defined in the Object
class. Try extend
ing an instance. It is one of the most elegant ways, as it supports code reuse and seems to me very object-oriented:
class Foo
def bar
puts "Hi"
end
end
module Bar
def foo
puts "Bye"
end
end
f = Foo.new
f.bar
#=> hi
f.extend Bar
f.foo
#=> bye
f.methods(false)
#=> []
# the module we extended from is not a superclass
# therefore, this must be empty, as expected
f.singleton_methods
#=> ["foo"]
# this lists the singleton method correctly
g = Foo.new
g.foo
#=> NoMethodError
Edit: In the comment you asked why methods(false)
returns nothing in this case. After reading through the C code it seems that:
methods
returns all the methods available for the object (also the ones in included modules)singleton_methods
returns all the singleton methods for the object (also the ones in included modules) (documentation)singleton_methods(false)
returns all the singleton methods for the object, but not those declared in included modulesmethods(false)
supposedly returns the singleton methods by callingsingleton_methods
, but it also passes the parameterfalse
to it; whether this is a bug or a feature - I do not know
Hopefully, this clarifies the issue a little. Bottom line: call singleton_methods
, seems more reliable.
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.
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!!!
Methods_added for Singleton methods, but not Class methods
Eureka!
AN_OBJECT = Object.new
def AN_OBJECT.methods_added
@@methods_added ||= []
end
def AN_OBJECT.singleton_methods_added
@@singleton_methods_added ||= []
end
def AN_OBJECT.singleton_method_added(method_name)
@@singleton_methods_added ||= []
@@singleton_methods_added << method_name
end
If you look at the previous excercise if you scroll up, it should give you enough hint on how to handle it. It's a tragedy that I posted this so much later..
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.
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.
What is `singleton_class` method in class and object?
Object#methods
returns the methods of that object. Methods defined in a class aren't methods of that class object, they are methods of that class's instances.
This has nothing to do with singleton classes, it's true for all classes:
class Foo
def bar; end
end
Foo.methods.include?(:bar)
# => false
Foo.new.methods.include?(:bar)
# => true
Foo.instance_methods
# => [:bar]
Here's how that works with your example:
User.methods.grep(/specific/)
# => [:specific_data1, :specific_data2]
User.singleton_methods
# => [:specific_data1, :specific_data2]
User.singleton_class.instance_methods.grep(/specific/)
# => [:specific_data1, :specific_data2]
Ruby ancestors method for singleton class objects
I think you'll really like the ruby 2.1
then!
$ rbenv local 2.1.0
roman.brodetski@nb-rbrodetski []
$ irb
...
irb(main):008:0> B.singleton_class.ancestors
=> [#<Class:B>, ClassMethods, #<Class:A>, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]
irb(main):009:0>
I also think it's a great thing that your mind is synchronized with the language developers!
Here is the redmine issue: https://bugs.ruby-lang.org/issues/8035
Related Topics
Creating Categories on Jekyll Driven Site
How to Read the Body Text of an Email Using Ruby's Net/Imap Library
Ruby Classes: Initialize Self VS. @Variable
How to Use Nokogiri to Parse an Xml File
Starting or Restarting Unicorn with Capistrano 3.X
Anybody Tried the Crystal Programming Language (Machine-Code Compiled Ruby)
Sidekiq List All Jobs [Queued + Running]
How to Specify Post Params in a Rails Test
How to Convert an Existing Rails 3 Application into an Engine
Deleting Table from Schema - Rails
Multiple Robots.Txt for Subdomains in Rails
Augmenting a Model from an External Gem
Check Ruby Http Response for Success
How to Attach a Message to Rspec Check
Rails 5.2.0 with Ruby 2.5.1 Console - 'Warning:' 'Already' Initialized Constant Fileutils::Version
What Are the Main Differences Between Sinatra and Ramaze