Ваши две части кода делают совершенно разные вещи. Используя instance_eval, вы оцениваете блок в контексте вашего объекта. Это означает, что использование def определит методы для этого объекта. Это также означает, что вызов метода без получателя внутри блока вызовет его для вашего объекта.
При выдаче себя вы передаете себя в качестве аргумента блоку, но поскольку ваш блок не принимает никаких аргументов, он просто игнорируется. Так что в этом случае самоотдача делает то же самое, что и ничто. def
здесь ведет себя точно так же, как и def
вне блока, выход на себя фактически не меняет то, для чего вы определяете метод. Что вы могли бы сделать:
class Foo
def initialize
yield self if block_given?
end
end
x = Foo.new {|obj| def obj.foo() 'foo' end}
x.foo
Разница с instance_eval заключается в том, что вы должны явно указать получателя.
Изменить, чтобы уточнить:
В версии с yield, obj в блоке будет полученным объектом, который в данном случае является вновь созданным экземпляром Foo. Хотя self будет иметь то же значение, что и вне блока. С версией instance_eval self
внутри блока будет только что созданный экземпляр Foo.