Ruby方法范围?

时间:2017-07-17 18:53:04

标签: ruby methods scope

在以下示例中:

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定义)

3 个答案:

答案 0 :(得分:3)

在没有附加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对象的上下文中,因此可以从{{1}调用multiply方法}}或ExampleClass.new或来自任何其他类。

来源:Wikipedia

<强>更新

engineersmnky评论中的一些注释。

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

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

  3. 它不一定是Array.new的实例,例如class因为类本身也会定义此方法,例如Class.new

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

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

因此,mainObject的私有实例方法。

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

所以,会发生以下情况:

  1. 您将main定义为Object
  2. 的私有实例方法
  3. 您致电main,然后将multiply定义为Object的公共实例方法
  4. 您致电multiply,这是有效的,因为objExampleClass的一个实例,它是Object的子类,具有您的multiply方法