ruby 顶层定义的方法在哪里?

Posted

技术标签:

【中文标题】ruby 顶层定义的方法在哪里?【英文标题】:Where are methods defined at the ruby top level? 【发布时间】:2010-12-18 04:24:23 【问题描述】:

在顶层,方法定义应该导致Object 上的私有方法,测试似乎证实了这一点:

def hello; "hello world"; end

Object.private_instance_methods.include?(:hello) #=> true
Object.new.send(:hello) #=> "hello world"

但是,以下也适用于顶层(self.metamain 的特征类):

self.meta.private_instance_methods(false).include?(:hello) #=> true

似乎hello 方法同时定义在 main 的特征类和 Object 上。这是怎么回事?请注意,private_instance_methodsfalse 参数不包括方法列表中的超类方法。

【问题讨论】:

类的简写 @Andrew 抱歉,这是 ruby​​ 1.9 如果是 Ruby 1.9,为什么不让事情变得更清楚并使用self.singleton_class 【参考方案1】:

首先,这种行为和背后的推理一直存在;这对 1.9 来说并不是什么新鲜事。它发生的技术原因是因为main 是特殊的,并且与任何其他对象都不同。没有花哨的解释:它的行为方式是这样的,因为它是这样设计的。

好的,但是为什么呢? main 神奇的原因是什么?因为 Ruby 的设计师 Yukihiro Matsumoto 认为 makes the language better 有这种行为:

是这样,为什么***方法没有在这个对象上做成单例方法, 而不是作为 Object 类的实例方法引入 本身 (因此进入所有其他类,即比现在更多的命名空间污染 通常是有意的)。这仍然允许***方法调用其他方法 ***方法。如果***对象被引用 一些 像 Main 这样的常量,那么可以从任何地方调用这些方法 和 Main.method(...).

你真的想输入 “Main.print”无处不在?

在进一步的讨论中,他解释说它的行为方式是因为他觉得“假设是自然的”。

编辑:

针对您的评论,您的问题是针对为什么 main 的 eigenclass 似乎将 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

好的,但是如果我们真的想知道给定函数是在 eigenclass 上定义的,而不是在原始类上定义的呢?

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

【讨论】:

嗨,谢谢 :D 尽管如此,Bar.new.meta.private_instance_methods(false).include?(:bar) 对 Bar 上定义的方法应该返回 true 对我来说感觉像是一个错误。谢谢:) 对此我也感到有些惊讶,但 Ruby 中的大多数事情一开始都让我感到惊讶。对于 Ruby,似乎最好的意识形态是生死存亡。 可能值得一提的是,这个答案的第二部分不适用于 Ruby 2,至少在 Ruby 2.5 中self.singleton_class.private_instance_methods(false).include?(:foo) 将返回 false

以上是关于ruby 顶层定义的方法在哪里?的主要内容,如果未能解决你的问题,请参考以下文章

Ruby / Rails——从哪里包含一个方法? [复制]

Ruby 的 have_header 方法在哪里查找头文件?

我在哪里可以编写要在部分中使用的方法? (Ruby on Rails)

在 Ruby on Rails 项目中将“关注点”存储在哪里? (轨道 5.2+)

添加渐变作为视图顶层的最佳方法是啥?

有啥作用!意味着在 Ruby 方法定义的末尾? [复制]