gpt4 book ai didi

ruby - Ruby MetaProgramming 中的一个令人困惑的案例

转载 作者:数据小太阳 更新时间:2023-10-29 07:32:31 24 4
gpt4 key购买 nike

我是 Ruby 元编程的初学者。在 irb 中练习我的代码时,我遇到了这个问题。

class A; end
a = A.new
b = class << a; self; end

b.instance_eval { def foo; puts 'foo'; end }
# => works for b.foo

b.instance_eval { define_method :bar do; puts 'bar'; end }
# => WHY this one works for a.bar rather than b.bar

最后的代码片段让我很困惑。


感谢您的具体回答,但也许我没有解释清楚我的困惑。我真正想了解的是为什么 define_method 在这些情况下的行为如此不同,在这里:

class A
def foo1
p 'foo1 from A'
end

define_method :bar1 do
p 'bar1 from A'
end
end

a = A.new
a.foo1 # => 'foo1 from A'
a.bar1 # => 'bar1 from A'


a.instance_eval { def foo2; p 'foo2 from a.metaclass'; end }
a.foo2 # => 'foo2 from a.metaclass'
a.instance_eval { define_method :bar2 do; p 'bar2 from a.metaclass'; end }
# => NoMethodError: undefined method `define_method' for #<A:0x000000016a2e70>

aa = class << a; self; end
aa.instance_eval { def foo3; p 'foo3 from a.metaclass.metaclass'; end }
aa.foo3 # => 'foo3 from a.metaclass.metaclass'
aa.instance_eval { define_method :bar3 do; p 'bar3 from a.metaclass.metaclss'; end }
aa.bar3 # => NoMethodError: undefined method `bar3' for #<Class:#<A:0x000000016a2e70>>
a.bar3 # => 'bar3 from a.metaclass.metaclss'

我知道这不会出现在日常编码中,但我想澄清一下。


得出结论:

aa = class << a; self; end 

aa.instance_eval { def foo; puts 'foo..'; end }

# defines a singleton-method for aa
aa.foo # => 'foo...'


aa.instance_eval { define_method :bar do; puts 'bar..'; end }
# equals
aa.class_eval { def bar; puts 'bar..'; end }

# both define a singleton-method for a,
# as define_method and class_eval both define instance_method
a.bar # => 'bar...'

最佳答案

除了所有其他评论:

[来自 Pickaxe] Object#instance_eval 方法可让您将 self 设置为某个任意对象,使用 [self] 计算 block 中的代码,然后重置 self。
和 Module#define_method :在接收器中定义实例方法 [self,它必须是(匿名)类或模块]。

singleton_class_of_object_a = aa = class << a; self; end
aa.instance_eval { def foo3; puts "foo3 from singleton class of a, self=#{self}"; end }
aa.foo3 # => foo3 from singleton class of a, self=#<Class:#<A:0x007fc2e4049e68>>
aa.instance_eval do
puts "about to define_method :bar3 in self=#{self}"
define_method :bar3 do; puts "bar3 from singleton class of a, self=#{self}"; end
end # => about to define_method :bar3 in self=#<Class:#<A:0x007fc2e4049e68>>
a.bar3 # => bar3 from singleton class of a, self=#<A:0x007fc2e4049e68>

define_method :bar3在 singleton_class_of_object_a(匿名类,见下文)的上下文中执行,因此定义了该类的实例方法,因此 bar3 成为 a 的单例方法。正如我之前的回答中已经说过的,它相当于直接在对象上定义:

def a.bar4; puts 'bar4 from singleton class of a' end
a.bar4 # => bar4 from singleton class of a

p a.singleton_methods.sort # => [:bar3, :bar4, :foo2]
p a.methods(false).sort # => [:bar3, :bar4, :foo2]


a = A.new之后,实例a的字段类指向类A
class << adef a.bar4 ,Ruby创建了一个匿名类,实例a的字段类现在指向这个匿名类,并从那里指向A
在此上下文中使用 def 定义的方法或 define_method进入匿名类的方法表。

关于ruby - Ruby MetaProgramming 中的一个令人困惑的案例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13775794/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com