Ruby self.class.class_eval или singleton_class.class_eval
В чем разница, когда я делаю
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.
Tass ответил, что в этом примере 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 >
Ответы
Ответ 1
Разница между экземплярами этих классов 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
Ответ 2
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
.