通过山寨 require 和 load 方法来解释它们的区别和联系
我就直接贴链接啦:
http://terrytai.com/articles/shaizhai-require-load
Hope you will like it :)
看楼主提供的山寨版的 load, 给我一个错觉,就是楼主认为 eval 和 load 是等价的。所以用 eval 来实现 load. (虽然真实的 load 貌似是 C 实现的), 我想问一个问题,在你写山寨版 load 时,你有考虑过 load 和 eval 的区别吗?
看代码:
module Kernel
def load1(fn)
eval File.read(fn)
end
end
load1 './person.rb'
p Person # => Kernel::Person
而如果用常规的 load.
module Kernel
def load1(fn)
load fn
end
end
load1 './person.rb'
p Person # => Person.
因为 Person.rb 一个臆造的文件,而你仅仅使用一个 puts 输出来验证 load 是否正确,肯定不妥。(不管在那个上下文空间被执行,都会 puts), 而如果需要确保第一个 load1 工作的像 load 那样,也只有定义在 Object 中,作为一个私有方法,才有可能正确。
好吧,如果我说这些有些多余 (楼主根本没这么想), 就当我上面废话好了。
我的实现和 c 语言版并不是完全等同的。
所以我叫他山寨,而并不是要写一个 load 方法的 ruby 实现... 所以我并没有先定义出 load 的 spce 是什么,写测试,再让它 pass。如你所说我甚至都没有在 module Kernel 中定义方法,而就在当前文件做了定义。
这个地方只是为了讲解啦 :)
感谢你如此严谨和细心... 哈哈哈哈哈~~ 不错....
#9 楼 @zw963 @poshboytl
刚好我写了篇:关于类名常量,想过这个问题。http://ruby-china.org/topics/10608
打开 Object 类即可做到一致了。
#打开Object类,Object mixin Kernel,所以可以覆盖kernel中的方法
class Object
def load1(fn)
eval File.read(fn)
end
end
load1 './person.rb'
p Person # => Person.
如果要原生 load 一样,放入 Kernel,可以使用 class_eval。
module Kernel
def load3(fn)
Object.class_eval %{
eval File.read(fn)
}
end
end
load3 './person.rb'
p Person
#=>Person
self.class.method(:load3)
#=>#<Method: Class(Kernel)#load3>
self.class.method(:load)
#=>#<Method: Class(Kernel)#load>