Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ruby self.class.class_eval or singleton_class.class_eval

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 > 
like image 343
Fivell Avatar asked Jan 30 '12 16:01

Fivell


1 Answers

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
like image 186
Aliaksei Kliuchnikau Avatar answered Dec 22 '22 05:12

Aliaksei Kliuchnikau