2016-03-08 2 views

ответ

6

Классы в рубине открыты. Поскольку Hello был предоставлен новым методом, метод отправки по всем экземплярам обновляется с этим. Если вы хотите продлить a только позвонить class_eval на eigenclass a «s:

class Hello; end 

a = Hello.new 

class << a; def world; puts "Hi" end end 
# or, the equivalent: 
# a.singleton_class.class_eval { def world; puts "Hi" end } 

b = Hello.new 

a.world #⇒ "Hi" 
b.world #⇒ NoMethodError: undefined method `world' for #<Hello> 
+2

Вам не нужен 'class_eval {' ... '}'. – sawa

+0

@sawa Я раб копий. Thx, обновлено. – mudasobwa

0

Почему создан a до того class_eval в коде есть доступ к world?

Это не так. Методы хранятся в модулях, а не в экземплярах. (Ну, модули являются экземплярами Module, но это не имеет значения здесь.) Все a знает, что это экземпляр Hello, то есть его указатель class указывает на Hello (опять же, технически это не так, его указатель class указывает на его одноточечный класс и его указатель superclass одного оконечного устройства указывает на Hello, но это также не имеет значения здесь). Когда a отправляется сообщение world, он проверяет свой класс, Hello, на метод world, и, конечно же, есть один, потому что он был добавлен до отправки сообщения, поэтому он его выполняет.

Как работает class_eval Работает за кулисами?

Это не имеет никакого отношения к class_eval, оно будет работать точно так же без метапрограммирования. class_eval - это красная сельдь:

class Hello; end 

a = Hello.new 

class Hello; def world; puts "Hi" end end 

b = Hello.new 

a.world # "Hi" 
b.world # "Hi"