在另一个方法中定义的方法范围

Scope of method defined inside another method

考虑以下代码:

class Emotion
  def confused?
    def confused?
      'yes'
    end
    'no'
  end
end

am_i = Emotion.new

am_i.confused? # => "no"
am_i.confused? # => "yes"

5.times.map { Emotion.new.confused? } # => ["yes", "yes", "yes", "yes", "yes"]

解释:

  1. 第一次运行 confused? returns "no" 并且 重新定义 本身。
  2. 第二次运行confused?会调用returns"yes".
  3. 的新方法

虽然上面的功能很清楚,但我不确定如何将这两种方法定义到相同的 scope

我问的原因是因为:

A variable cannot be accessed in similar fashion inside and outside a method; for instance: if I define @variable inside and outside a method it has different meanings.

使用@x = y语法设置实例变量时,实例变量设置为self

I have learned that method definition changes self. Won't the inside definition of the confused? method have a different scope in comparison with the outside definition?

范围可以改变,但在这种情况下不会。方法中 self 的值始终是调用该方法的对象。在您的两个 confused? 方法定义中,selfEmotion.

的一个实例

How does def actually determine where to define the method?

这个问题的答案(至少在 MRI 中)实际上有些不直观。每个作用域都有对 "default definee" 对象的引用,该对象不一定与 self 相关,并且始终是 Module 的实例。 def 在该范围内将为默认定义者定义一个方法。在 ruby 代码中获取默认定义的最简单的方法是:

eval("def __m; end; m = method(:__m); undef __m; m.owner")

例如,运行 在 ruby 程序的顶层 returns Object。因此,顶级范围的默认定义是 Object.

下面是一些代码,希望能回答您关于作用域的问题:

# `self` is the toplevel object
# default definee is `Object`

class X
  # `self` is X
  # default definee is also X

  @a = 1 # defines instance variable @a for `X`

  def y # defines method 'y' on X

    # `self` is an instance of X
    # default definee is X

    @b = 2 # defines instance variable @b for an instance of `X`

    def z # defines method 'z' on X

      # `self` is still an instance of X
      # default definee is still X

      @c = 3 # defines instance variable @c for an instance of `X`

    end
  end

  class << self
    # `self` is the metaclass of X
    # default definee is also the metaclass of X

    @d = 4 # defines instance variable @d for the metaclass of X
  end
end

重要的是要记住 方法 总是存储在 Module 的实例中,其中 实例变量 可以是存储在任何对象中(不包括 nil 或布尔值或整数等原语)。