ruby self.class.class_eval или singleton_class.class_eval - PullRequest
10 голосов
/ 30 января 2012

Какая разница, когда я делаю

class T

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

end

и

class T

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

end

Спасибо

PS.ТАСС ответил, что в этом примере singleton_class будет возвращать разные object_id для каждого нового объекта, потому что singleton_class принадлежит только одному объекту.Но IRB показывает следующее

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 > 

Ответы [ 2 ]

12 голосов
/ 30 января 2012

Разница между экземплярами этих T классов заключается в алгоритме поиска метода: метод всегда ищется в одноэлементном классе (и его модулях), и только если он здесь не найден, онпоиск в классе .

Это означает, что если мы добавим метод test к первой реализации класса T после инициализации, мы получим другой результат, чем когда мы сделаем то же самое для второйреализация класса 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
8 голосов
/ 30 января 2012

singleton_class дает вам Class, который уникален для этого объекта.self.class дает вам класс, который разделяют все объекты этого Class. Пример

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

В приведенном выше примере singleton_class будет возвращать разные object_id для каждого нового объекта, поскольку singleton_class принадлежит только одному Object.self.class вернет то же самое, потому что self.class указывает на один и тот же Class каждый раз.

...