Ruby 改进陷阱
Ruby refinements gotchas
在第 2 章的 Metaprogramming Ruby 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
之后使用,作者在这里想说什么?
谁能提供更多intuitive/better解释?
谢谢。
我能找到的最好的解释来自 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
之后的某处调用。调用方法的实际位置才是最重要的,而不是调用方法的方式或调用方法的位置。
事情是这样的。
using
即 using MyClassRefinement
激活 my_method
细化。
MyClass.new.my_method
被执行。
- 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
- 优化 有效,并且
my_method
returns 来自优化的代码 "refined my_method()"
MyClass.new.another_method
被执行。
- method lookup 从确切的调用点开始。
- 细化 在调用的这一点上处于活动状态 ,但
another_method
不是细化,因此 Ruby 在中查找 another_method
class MyClass
并找到它。
- 在 class 方法
another_method
中,找到并调用方法 my_method
。
- method lookup 从确切的调用点开始。
- 在调用点,没有任何改进处于活动状态,因为没有调用
using
行上方 (即物理上先于),其中 my_method
被调用。 Ruby 继续在 class MyClass
中寻找 my_method
并找到它。
my_method
returns 来自 class 方法的代码 "original my_method()"
。
我们可以做一个简单的比较。假设我有一个隔离的 file.rb
,代码如下:
puts puppy
puppy = 'waggle'
puppy
未定义前不能使用。该变量是词法范围的,其使用取决于其定义在隔离 file.rb
.
中的位置
类似地,细化只有在前一行(或源代码文件中物理上的某处)通过using
激活后才能被调用。细化为lexically scoped.
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
语句在文件中的物理位置如何确定优化是否处于活动状态。
在第 2 章的 Metaprogramming Ruby 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 callanother_method
afterusing
, the call tomy_method
itself happens beforeusing
— so it calls the original, unrefined version of the method.
这完全把我绊倒了。
为什么 MyClass.new.another_method
打印 "original my_method()" 因为它在 using MyClassRefinement
之后使用,作者在这里想说什么?
谁能提供更多intuitive/better解释?
谢谢。
我能找到的最好的解释来自 the docs:
Refinements are lexical in scope. Refinements are only active within a scope after the call to
using
. Any code before theusing
statement will not have the refinement activated.
这意味着您的优化方法必须在调用 using
之后的某处调用。调用方法的实际位置才是最重要的,而不是调用方法的方式或调用方法的位置。
事情是这样的。
using
即using MyClassRefinement
激活my_method
细化。MyClass.new.my_method
被执行。- 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
- 优化 有效,并且
my_method
returns 来自优化的代码"refined my_method()"
MyClass.new.another_method
被执行。- method lookup 从确切的调用点开始。
- 细化 在调用的这一点上处于活动状态 ,但
another_method
不是细化,因此 Ruby 在中查找another_method
classMyClass
并找到它。 - 在 class 方法
another_method
中,找到并调用方法my_method
。 - method lookup 从确切的调用点开始。
- 在调用点,没有任何改进处于活动状态,因为没有调用
using
行上方 (即物理上先于),其中my_method
被调用。 Ruby 继续在 classMyClass
中寻找my_method
并找到它。 my_method
returns 来自 class 方法的代码"original my_method()"
。
我们可以做一个简单的比较。假设我有一个隔离的 file.rb
,代码如下:
puts puppy
puppy = 'waggle'
puppy
未定义前不能使用。该变量是词法范围的,其使用取决于其定义在隔离 file.rb
.
类似地,细化只有在前一行(或源代码文件中物理上的某处)通过using
激活后才能被调用。细化为lexically scoped.
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
语句在文件中的物理位置如何确定优化是否处于活动状态。