2

我决定尝试在 Ruby 中的方法中定义方法并写下:

def foo
  def bar
    puts "hello"
  end
  bar
end

这个定义,我跑了foo,“你好”按我的预期打印了。但是我然后尝试foo.bar了 - 它打印了两次“你好”。为什么?

4

3 回答 3

4

foo.bar等于foo().bar()所以你首先调用foo包含bar所以它在这里执行一次,然后再bar执行一次。最后bar被调用两次。

def foo
  puts 'foo called'
  def bar
    puts 'bar called'
    puts "hello"
  end
  bar
end
foo.bar
#=> foo called
#=> bar called
#=> hello
#=> bar called
#=> hello

我不明白的是这意味着结果foonil可以调用bar

>> nil.bar
#=> hello

这怎么可能?

编辑:正如一些答案中所解释的,嵌套方法包含在类范围内,因此在 foo 内部或外部声明 bar 没有任何区别。

Matz 也表示可能会从 Ruby2.0 更改

这是他写的例子:

class Foo
  def foo
    def bar
      #omited
    end
    bar # can be called
  end

  def quux
    bar # cannot be called
  end
end

edit-Ruby2.0:最终没有实现。所以它保持不变。

于 2012-09-21T07:06:43.430 回答
2

在 Ruby 中,有一个隐藏变量并没有引起太多关注。我不知道它叫什么,但我称它为当前类。这个变量是目标def

当你进入 时foo,它不会改变这个变量,你仍然在同一个班级。因此,当您在 foo 中定义另一个方法时,该方法将被定义在与 foo 定义相同的类上。

在这种情况下,您在顶级对象 main 上定义 foo。Main 的当前类变量设置为 object,因此您在此处定义的任何方法都将在任何对象中可用。

由于你做的最后一件事是返回 bar 的结果,而 bar 返回 nil(b/c puts 返回 nil),那么foo.baris nil.bar。而且由于您在 Object 上定义了 bar,因此即使 nil 也会继承此方法。

有趣的是,酒吧是公开的。由于 foo 是在 main 中定义的,并且 main 将其范围设置为私有,我本来希望 bar 也是私有的,但我想一旦你进入不同的范围,状态肯定会丢失。

于 2012-09-21T07:27:33.667 回答
1

你的意思是放class foo?似乎调用 foo.bar 调用函数 foo 然后调用函数 bar。呼叫nil.bar也会打印出“你好”。

于 2012-09-21T07:05:55.160 回答