gpt4 book ai didi

Ruby 改进陷阱

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

Metaprogramming Ruby 2在第 2 章的“Refinements”部分,我找到了以下 Ruby 代码:

class MyClass 
def my_method
"original my_method()"
end

def another_method
my_method
end

end

module MyClassRefinement
refine MyClass do
def my_method
"refined my_method()"
end
end
end

using MyClassRefinement
MyClass.new.my_method # => "refined my_method()"
MyClass.new.another_method # => "original my_method()" - How is this possible?

据作者说:

However, the call to another_method could catch you off guard: even if you call another_method after using, the call to my_method itself happens before using — so it calls the original, unrefined version of the method.

这完全把我绊倒了。

为什么 MyClass.new.another_method 打印“original my_method()”,因为它是在 using MyClassRefinement 之后使用的,作者在这里想表达什么?

谁能提供更直观/更好的解释?

谢谢。

最佳答案

我能找到的最好的解释来自 the docs :

Refinements are lexical in scope. Refinements are only active within a scope after the call to using. Any code before the using statement will not have the refinement activated.

这意味着您的优化方法必须在调用 using 之后的某处调用.调用方法的实际位置才是最重要的,而不是调用方法的方式或调用方法的位置。


这是发生了什么。

  1. usingusing MyClassRefinement激活 my_method细化。
  2. MyClass.new.my_method被执行。
  3. A method lookup从确切的调用点开始:

When looking up a method for an instance of class C Ruby checks:

  • If refinements are active for C, in the reverse order they were activated
    • The prepended modules from the refinement for C
    • The refinement for C
    • The included modules from the refinement for C
  • The prepended modules of C
  • C
  • The included modules of C
  1. 优化活跃,并且my_method返回细化的代码 "refined my_method()"
  2. MyClass.new.another_method被执行。
  3. method lookup从确切的调用点开始。
  4. 改进在这个调用点处于事件状态,但是another_method不是细化,所以 Ruby 寻找 another_method在类里面MyClass并找到它。
  5. 类方法内部another_method , 方法 my_method找到并调用。
  6. method lookup从确切的调用点开始。
  7. 在调用时没有优化事件,因为没有调用 using 在线之上(即物理上之前),其中 my_method被调用。 Ruby 继续寻找 my_method在类里面MyClass并找到它。
  8. my_method从类方法返回代码 "original my_method()" .

我们可以做一个简单的比较。假设我有一个隔离的 file.rb使用以下代码:

puts puppy
puppy = 'waggle'

puppy在定义之前不能使用。该变量是词法范围的,其使用取决于其定义在隔离的 file.rb 中的位置。 .

类似地,细化只有通过using激活后才能被调用。在前一行(或源代码文件中物理上的某个位置)。细化为 lexically scoped .

From Wikipedia

In languages with lexical scope (also called static scope), name resolution depends on the location in the source code and the lexical context, which is defined by where the named variable or function is defined...

Lexical resolution can be determined at compile time, and is also known as early binding, while dynamic resolution can in general only be determined at run time, and thus is known as late binding.


this article 的最后一节讨论了您关于改进的具体问题。 。作者还解释了 using语句在文件中的物理位置决定了细化是否处于事件状态。

关于Ruby 改进陷阱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46623706/

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