2017-10-07 51 views
5

Metaprogramming Ruby 2的 “加细” 一节,我发现了下面的一段Ruby代码:红宝石的改进在第2章陷阱

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? 

据笔者:

然而,呼叫到another_method 可能会引起您的后顾之忧:即使您在using之后致电another_method,致电my_method的呼叫本身也发生在using之前 - 所以它会调用原始的未定义版本的方法。

这完全让我失望。

为什么MyClass.new.another_method会打印“original my_method()”,因为它在using MyClassRefinement之后使用,作者在此尝试说些什么?

任何人都可以提供更直观/更好的解释吗?

谢谢。

+0

这可能是因为通过优化引入的重新映射仅适用于特定范围,并且在原始定义范围内,范围不受影响。 – tadman

回答

2

我能找到的最好的解释是从the docs

方案在范围词汇。只有在拨打using后,优化才会在范围内生效。在using声明之前的任何代码都不会激活细化。

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


这是发生了什么事。

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

当查找一个方法的class C红宝石检查一个实例:

  • 如果精炼是活性为C,在反向命令他们被激活
    • 来自C
    • C
  • C
  • 从细化所包含的模块的细化C
  • C
  • C
  • 加细是活性,并my_method"refined my_method()"
  • MyClass.new.another_method执行细化返回代码。
  • method lookup从确切的调用点开始。
  • 加细活跃在这一点上调用,但another_method不细化,使红宝石类MyClass查找another_method和发现它。
  • 在类方法another_method中,找到并调用方法my_method
  • method lookup从确切的调用点开始。
  • 在调用时没有激活的优化,因为在线(即物理上之前)之前没有调用using,其中my_method被调用。 Ruby继续在类MyClass中寻找my_method并找到它。
  • my_method返回类方法"original my_method()"的代码。
  • 我们可以做一个简单的对比。比方说,我有一个隔离file.rb用下面的代码:是指之前

    puts puppy 
    puppy = 'waggle' 
    

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

    同样,改进不能被调用,直到它已经通过using上一行(或物理上先前在源代码文件内的某个地方)激活。细化是lexically scoped

    From Wikipedia

    在具有词法作用域语言(也称为静态范围),名称解析取决于在源代码中的位置和词汇上下文,这是由其中所限定的命名变量或函数被定义...

    词法分辨率可以在编译时确定,也被称为早期绑定,而动态分辨率通常只能在运行时确定,因此被称为后期绑定


    你有改进的具体问题是在this article最后一节讨论。作者还解释了文件中using声明的物理位置如何确定是否处于活动状态。

    +0

    谢谢!现在它总是有意义的!词汇范围是真正的罪魁祸首。 – kstratis

    +0

    ...和您的参考文献帮助了很多! – kstratis

    +0

    没问题:)我很高兴它有帮助 –