gpt4 book ai didi

Ruby 自身和方法定义

转载 作者:数据小太阳 更新时间:2023-10-29 06:57:28 25 4
gpt4 key购买 nike

class MyClass
def one
def two
end
end
end

obj = MyClass.new
obj.one
puts obj.method(:two).owner #==> MyClass

这里我在另一个方法一中定义了方法二。方法一由 MyClass (obj) 的实例调用。所以定义方法二的时候self就是obj。当我检查方法二的所有者时,它是 MyClass

obj.instance_eval do
def three
end
end

puts obj.method(:three).owner #==> #<Class:#<MyClass:0x007f85db109010>>

在这段代码中,我对 obj 执行了 instance_eval,因此当定义了方法三时,self 又是 obj。但是当我检查 three 的所有者时,它是 obj 的单例类

这是为什么呢?除了 self 之外还有其他什么决定方法定义的去向吗??

最佳答案

我会使用 Kernel#set_trace_func方法,向您解释幕后发生的事情。先看下面的代码和输出:

trace = lambda do |event,file,line,id,binding,klass|
p [event,File.basename(file),line,id,binding,klass]
end


set_trace_func trace

class MyClass
def self.bar;end
def one
def two
end
end
end

obj = MyClass.new
obj.one
obj.instance_eval do
def three
end
end

输出:

-----------------
----------------
-----------------
-----------------
-----------------
----------------- # part A
["c-call", "test.rb", 9, :singleton_method_added, #<Binding:0x83ab2b0>, BasicObject]
["c-return", "test.rb", 9, :singleton_method_added, #<Binding:0x83aaeb4>, BasicObject]
["line", "test.rb", 10, nil, #<Binding:0x83aab80>, nil]
["c-call", "test.rb", 10, :method_added, #<Binding:0x83aa900>, Module]
["c-return", "test.rb", 10, :method_added, #<Binding:0x83aa07c>, Module]
----------------------------- # part B
["line", "test.rb", 16, nil, #<Binding:0x83a976c>, nil]
["c-call", "test.rb", 16, :new, #<Binding:0x83a9488>, Class]
["c-call", "test.rb", 16, :initialize, #<Binding:0x83a90a0>, BasicObject]
["c-return", "test.rb", 16, :initialize, #<Binding:0x83a8e20>, BasicObject]
["c-return", "test.rb", 16, :new, #<Binding:0x83a8b28>, Class]
---------------------------
---------------------------
--------------------------- # part C
["c-call", "test.rb", 11, :method_added, #<Binding:0x83a7de0>, Module]
["c-return", "test.rb", 11, :method_added, #<Binding:0x83a79f8>, Module]
--------------------------- # part D
["line", "test.rb", 18, nil, #<Binding:0x83a7034>, nil]
["c-call", "test.rb", 18, :instance_eval, #<Binding:0x83a6c10>, BasicObject]
["line", "test.rb", 19, nil, #<Binding:0x83a65f8>, nil]
["c-call", "test.rb", 19, :singleton_method_added, #<Binding:0x83a61d4>, BasicObject]
["c-return", "test.rb", 19, :singleton_method_added, #<Binding:0x83a5ef0>, BasicObject]
["c-return", "test.rb", 18, :instance_eval, #<Binding:0x83a5d4c>, BasicObject]

解释:

请查看 A 部分 下方的 5 行。它只是告诉我们,当 Ruby 会在类中找到 def 关键字时,它会将该方法作为实例方法添加到该类中。这是通过调用钩子(Hook)方法来完成的 Module#method_added . C 部分 下面的两行也有同样的解释。

现在 obj.instance_eval {..} 内部发生了什么?

好的,如果您查看D 部分 下面的行,这将被清除。从最后、firstsecond 行看。在 instance_eval block 内,def third 导致 third 作为对象 obsingleton_method 添加,通过调用钩子(Hook)方法 BasicObject#singleton_method_added .

MRI 就是这样写的。

关于Ruby 自身和方法定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20311737/

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