10

What is difference when I do

class T

  def initialize
   self.class.class_eval do
      def test
        return self.class.object_id
     end
   end
  end

end

and

class T

  def initialize
    singleton_class.class_eval do
      def test
        return self.class.object_id
     end
   end
  end

end

Thanks

PS. Tass answered that in this example , singleton_class will return a different object_id for each new object, because a singleton_class belongs to one Object only. But IRB shows next

1.9.2p180 :001 > class T
1.9.2p180 :002?>   
1.9.2p180 :003 >     def initialize
1.9.2p180 :004?>      singleton_class.class_eval do
1.9.2p180 :005 >               def test
1.9.2p180 :006?>                 return self.class.object_id
1.9.2p180 :007?>              end
1.9.2p180 :008?>        end
1.9.2p180 :009?>     end
1.9.2p180 :010?>   
1.9.2p180 :011 >     end
 => nil 
1.9.2p180 :012 > t = T.new
 => #<T:0x00000100ae9cb8> 
1.9.2p180 :013 > t1 = T.new
 => #<T:0x00000100ad7ef0> 
1.9.2p180 :014 > t1.test == t.test
 => true 
1.9.2p180 :015 > t1.test
 => 2153233300 
1.9.2p180 :016 > t.test
 => 2153233300 
1.9.2p180 :017 > 
Abdullah
  • 2,015
  • 2
  • 20
  • 29
Fivell
  • 11,829
  • 3
  • 61
  • 99

2 Answers2

12

The difference between instances of these T classes is in the method lookup algorithm: method is always searched in the singleton class (and its modules) and only if it is not found here, it is searched in the class.

This mean if we add method test to the first implementation of class T after initialization we will get different result than when we do the same for second implementation of class T:

# First example
class T
  def initialize
    self.class.class_eval do
      def test
        return self.class.object_id
      end
    end
  end
end

t = T.new

class T
  def test
    'overriden'
  end
end

puts t.test # => 'overriden'

class T
  def initialize
    singleton_class.class_eval do
      def test
        return self.class.object_id
      end
    end
  end
end

t = T.new

class T
  def test
    'overriden'
  end
end

puts t.test # => 77697390
Aliaksei Kliuchnikau
  • 13,589
  • 4
  • 59
  • 72
  • From a practical standpoint, when would you do one over the other? – Claw Jan 31 '12 at 01:44
  • @Claw, methods above are just curious testing samples, I would not write anything like this in initializer of real class. Generally: add methods to the *class* when you need to add the method to *all* instances of the class and add method to *singleton class* when you need to add the method to a *single* instance of the class. In example 2 OP adds method to *singleton class* of *each* method instance (in initializer) - this is not practical, add method to *class* in such situations. – Aliaksei Kliuchnikau Jan 31 '12 at 10:35
8

singleton_class gives you the Class that is unique to that object. self.class gives you the class that all objects of that Class share. Example

foobar = Array.new

# this defines a method on the singleton class
def foobar.size
  "Hello World!"
end

foobar.size  # => "Hello World!"
foobar.class # => Array

bizbat = Array.new
bizbat.size  # => 0

In the example above, singleton_class will return a different object_id for each new object, because a singleton_class belongs to one Object only. self.class will return the same because self.class does point to the same Class every time.

Reactormonk
  • 21,472
  • 14
  • 74
  • 123
  • 2
    That follows pretty much directly from the docs. But it's not an answer to the question. What difference do the two approaches actually make in the code above? – Jakub Hampl Jan 30 '12 at 16:22
  • 1
    Looks like OP asks not what is the difference between class and singleton class, but what is the difference between these two examples he provided from the program execution point of view. In both cases instances of `T` will have instance with method `test`, and how are they different? – Aliaksei Kliuchnikau Jan 30 '12 at 16:58
  • thanks for response, Alex, sure, I want to understand diffrerence wich you mentioned – Fivell Jan 30 '12 at 17:01