【问题标题】:Ruby method scope?Ruby 方法范围?
【发布时间】:2017-12-22 10:13:34
【问题描述】:

在下面的例子中:

Main.rb

def main
  obj = ExampleClass.new
  def multiply(a, b, c, d)
    return a * b * c * d
  end
  puts obj.multiply(1, 2, 3, 4) # this prints 24
end
main

ExampleClass.rb

class ExampleClass
  def initialize

  end
end

为什么multiply 方法现在是obj 实例的一部分? (main 方法不是ExampleClass 定义的一部分)

【问题讨论】:

标签: ruby methods scope


【解决方案1】:

在脚本范围内定义的方法成为Object 的私有实例方法。 (除了在 IRb 中,它们成为 Objectpublic 实例方法。)

所以,mainObject 的私有实例方法。

方法内部的方法定义不创建嵌套方法,即multiply 不嵌套在main 中。相反,每次调用main 时,都会创建一个名为multiply 的新方法作为Object 的实例方法。由于某些我不太清楚的原因,它最终成为了一个 public 方法。

所以,会发生以下情况:

  1. 您将main 定义为Object 的私有实例方法
  2. 你调用main,这又将multiply定义为Object的公共实例方法
  3. 你调用multiply,因为objExampleClass的一个实例,它是Object的子类,它有你的multiply方法

【讨论】:

    【解决方案2】:

    没有附加class .. endmodule .. end 附件的代码直接在特殊main 对象的上下文中执行。可以使用以下方式引用此对象:

    2.2.2 :001 > self
    # => main 
    

    在没有额外 classes/modules 的情况下定义的方法被定义为 main 对象的私有方法,因此,在 Ruby 中几乎所有其他对象的私有方法:

    2.2.2 :002 > def foo
    2.2.2 :003?>   42
    2.2.2 :004?> end
    # => :foo 
    2.2.2 :005 > foo
    # => 42 
    2.2.2 :006 > [].foo
    # => NoMethodError: private method `foo' called for []:Array
    2.2.2 :007 > [].send :foo
    # => 42
    

    因此,在您的代码中,main 方法(或任何其他方法)位于 main 对象的上下文中,因此可以从 ExampleClass.newArray.new 或从任何其他类。

    来源:Wikipedia

    更新

    engineersmnky 的评论中的一些注释。

    1. 这不是 main 中的私有方法,而是 BasicObject 的私有方法(在 2.0-2.2 中)。

    2. 从 2.3(和 1.9.3)开始,此方法甚至没有私有化。

    3. 它不必是class 的实例,例如Class.new 作为类本身也将定义此方法,例如BasicObject.foo

    【讨论】:

    • 主方法没有封装在 ExampleClass 中。
    • 那么ExampleClass 是什么?提供ExampleClass的一些代码。
    • ExampleClass 是一个空类,我加进去了。
    • @aoiee 更新了答案。希望对您有所帮助。
    • 几点说明 1) 这不是main 中的私有方法,而是BasicObject 中的私有方法(在2.0-2.2 中)。 2) 从 2.3(和 1.9.3)开始,这种方法甚至没有私有化。 3)它不必是类的实例,例如Class.new 作为类本身也将定义此方法,例如BasicObject.foo
    【解决方案3】:

    可能是因为变量obj 和定义方法multiply 的上下文都将Object 作为父/祖先。

    如果您拨打obj.class,您将收到ExampleClass < Object。假设你在控制台中,如果你调用self.class,你会得到Object < BasicObject。因此,在您的代码中,您为 Object 类定义了一个方法 multiply。这就是为什么multiplyobj 实例的一部分。

    【讨论】:

    • Sort of... 在main 中定义的方法(不是OP 定义的方法,而是Object main)作为BasicObject 的实例方法自动添加,因为每个对象都继承,直接或间接地,从 BasicObject 开始,只要接收对象没有定义该方法的对象特定版本(直到 BasicObject 的任何祖先都没有定义该方法),该方法在任何地方都可用。
    • 在顶层定义的方法变成了Objectprivate实例方法,而不是BasicObject
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多