21

I am learning Ruby Singletons and i found some ways to define and get list of Class and Object singleton methods.

Class Singleton Methods

Ways to define class singleton methods:

class MyClass

  def MyClass.first_sing_method
    'first'
  end

  def self.second_sing_method
    'second'
  end

  class << self
    def third_sing_method
      'third'
    end
  end

  class << MyClass
    def fourth_sing_method
      'fourth'
    end
  end
end

def MyClass.fifth_sing_method
  'fifth'
end

MyClass.define_singleton_method(:sixth_sing_method) do
  'sixth'
end

Ways to get list of class singletons methods:

#get singleton methods list for class and it's ancestors 
MyClass.singleton_methods

#get singleton methods list for current class only  
MyClass.methods(false)

Object Singleton Methods

Ways to define object singleton methods

class MyClass
end

obj = MyClass.new

class << obj
  def first_sing_method
    'first'
  end
end

def obj.second_sing_method
  'second'
end

obj.define_singleton_method(:third_sing_method) do
  'third'
end

Way to get list of object singleton methods

#get singleton methods list for object and it's ancestors  
obj.singleton_methods

#get singleton methods list for current object only
obj.methods(false)

Are there other ways to do this?

2
  • 2
    Even though this question has been answered long ago, for completeness: you can also use methods class_eval and instance_eval. For instance: obj.instance_eval {def hi;puts "hi";end}, or Object.class_eval {def self.foo;puts "foo";end} (this is just the same as extending via open classes), or as last: Object.instance_eval{def bar;puts "bar";end} (this opens the virtual class of Object. Even though self is the same as the previous,it still is in a different environment!) Commented Jan 9, 2013 at 8:36
  • Nice sum up, should be a wiki Commented Aug 28, 2014 at 15:54

3 Answers 3

13

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 extending 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 modules
  • methods(false) supposedly returns the singleton methods by calling singleton_methods, but it also passes the parameter false 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.

Sign up to request clarification or add additional context in comments.

7 Comments

Thank you, nice feature, i didn't know about it. But why methods(false) don't show added method?
I can also extend class this way
I experimented with methods(false) and concluded that method(false) show only own object's methods, it not show methods from upper classes in ancestor chain
at previous deleted comment you said that methods() is alias for instance_methods(), is it true? In this case how instance_methods() can return singleton methods? Singleton and instance methods are different.
sorry for a lot of questions, but i try to understand
|
6

Some more ways:

Class singleton methods

class << MyClass
  define_method :sixth_sing_method do
    puts "sixth"
  end
end

class MyClass
  class << self
    define_method :fourth_sing_method do
      puts "seventh"
    end
  end
end

Object singleton methods

class << obj
  define_method :fourth_sing_method do
    puts "fourth"
  end
end

Next, you can use define_method and define_singleton_method in combination with send, e.g.

obj.send :define_singleton_method, :nth_sing_method, lambda{ puts "nth" }

and all possible combinations thereof. To use define_method, you need to capture the singleton class first as in this (the same works for class objects, too)

singleton_class = class << obj; self end
singleton_class.send :define_method, :nth_sing_method, lambda{ puts "nth" }

Another ways is using class_eval on the singleton class objects:

singleton_class.class_eval do
  def nth_sing_method
    puts "nth"
  end
end

And then you once again may combine send with class_eval...

There are myriads of ways, I guess :)

Comments

1

Object singleton methods

instance_eval

class A
end

a = A.new

a.instance_eval do
def v 
"asd"
end
end

 a.singleton_methods
 => [:z, :v] 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.