在顶层,方法定义应该导致Object
上的私有方法,并且测试似乎证实了这一点:
def hello; "hello world"; end
Object.private_instance_methods.include?(:hello) #=> true
Object.new.send(:hello) #=> "hello world"
但是,以下内容也适用于顶层(self.meta
是main
的本征类):
self.meta.private_instance_methods(false).include?(:hello) #=> true
似乎hello
方法同时在main的本征类和Object
上定义。这是怎么回事?请注意,false
的{{1}}参数会从方法列表中排除超类方法。
答案 0 :(得分:8)
首先,这种行为和潜在的推理一直存在;这对1.9来说并不新鲜。它发生的技术原因是因为main
是特殊的,并且与任何其他对象的处理方式不同。没有任何花哨的解释:它的行为方式是因为它是这样设计的。
好的,但为什么呢? main
神奇的原因是什么?因为Ruby的设计师Yukihiro Matsumoto认为它makes the language better有这种行为:
是这样,为什么顶层方法没有在这个对象上制作单例方法, 而不是像Object类中的实例方法一样被拉入 本身 (因此进入所有其他类别,即更多的命名空间污染 通常打算)。这仍然允许顶级方法调用其他方法 顶级方法。如果顶级对象被引用 一些 像Main这样的常量,那些方法可以从任何地方调用 同 Main.method(...)。
你真的想打字吗? 到处都是“Main.print”?
在讨论中,他解释说它的行为方式是因为他觉得“假设很自然。”
在回答您的评论时,您的问题是针对为什么main的本征类似乎将hello
报告为私有实例方法。问题在于,没有任何顶级函数实际添加到main
,而是直接添加到Object
。使用本征类时,instance_methods
函数族的行为总是表现为本征类仍然是原始类。也就是说,类中定义的方法被视为直接在本征类中定义。例如:
class Object
private
def foo
"foo"
end
end
self.send :foo # => "foo"
Object.private_instance_methods(false).include? :foo # => true
self.meta.private_instance_methods(false).include? :foo # => true
class Bar
private
def bar
"bar"
end
end
bar = Bar.new
bar.send :bar # => "bar"
Bar.private_instance_methods(false).include? :bar # => true
bar.meta.private_instance_methods(false).include? :bar # => true
我们可以直接将方法添加到main
的本征类中。将您的原始示例与此进行比较:
def self.hello; "hello world"; end
Object.instance_methods.include? :hello # => false
self.meta.instance_methods.include? :hello # => true
好的,但如果我们真的想知道给定的函数是在本征类上定义的,而不是原始的类呢?
def foo; "foo"; end #Remember, this defines it in Object, not on main
def self.bar; "bar"; end #This is defined on main, not Object
foo # => "foo"
bar # => "bar"
self.singleton_methods.include? :foo # => false
self.singleton_methods.include? :bar # => true