Сначала подумайте, что делает include
.он делает методы instance модуля включаемыми в методы instance включающего класса.т.е. кроме того факта, что ваш рабочий пример использует анонимный модуль, он эквивалентен:
module M1
def lab
puts 'm'
end
end
class Foo
include M1
def lab
super
puts 'c'
end
end
Далее, подумайте, что делает class_eval
.Он оценивает данный код в контексте класса или модуля.то есть, точно так же, как вы снова открыли модуль и набрали код, переданный class_eval
.Так что MyModule = Module.new { class_eval "def lab; puts 'm' end" }
эквивалентно
module MyModule
def lab
puts 'm'
end
end
Надеюсь, это объясняет, что работает.
Когда вы используете instance_eval
, вы оцениваете код в контексте принимающего объекта (вв данном случае это экземпляр модуля), поэтому MyMod2 = Module.new { instance_eval "def lab; puts 'm' end" }
эквивалентен
module MyMod2
def MyMod2.lab
puts 'm'
end
end
, т. е. он создает метод module , который вы вызываете через MyMod2.lab
, и такие методы не добавляютсякак методы экземпляра от include
.
Обратите внимание : этот ответ заимствует часть своего объяснения из ответа, который я написал на предыдущий вопрос о instance_eval vsclass_eval , относящийся к примеру из Ruby Programming Language book.Вам также может пригодиться этот ответ.