Ruby怎么在类定义上的显式范围?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (12)

代码取自rubykoans

这来自对类内常量范围的讨论。这是几个类的定义:

class Animal
  LEGS = 4
  def legs_in_animal
    LEGS
  end
end

class MyAnimals
  LEGS = 2

  class Bird < Animal
    def legs_in_bird
      LEGS
    end
  end
end

在这一点上做MyAnimals::Bird.new.legs_in_bird

然后定义这个类:

class MyAnimals::Oyster < Animal
  def legs_in_oyster
    LEGS
  end
end

提问于
用户回答回答于

我认为这个例子解释得最好。Ruby按以下顺序搜索常量定义:

  1. 封闭范围
  2. 外部范围
  3. 包含的模块
  4. Superclass(es)
  5. Top level
  6. Object
  7. Kernel
  8. EDIT

这种情况的一个例子:

FOO = 'I pity the foo!'

module One
  FOO = 'one'

  class Two
    FOO = 'two'

    def self.foo
      FOO
    end
  end

  class Three < Two
    def self.foo
      FOO
    end
  end
end

class Four
  class Five < Four
    def self.foo
      FOO
    end
  end
end

describe FOO do
  it "depends where it is defined" do
    expect(FOO).to eq 'I pity the foo!' # top-level
    expect(One::FOO).to eq 'one' # module
    expect(One::Two.foo).to eq 'two' # class
    expect(One::Three.foo).to eq 'one' # outer scope (One) comes before superclass
    expect(Four::Five.foo).to eq 'I pity the foo!' # top-level
  end
end
用户回答回答于

如果你在MyAnimals类定义中定义了Oyster,那么你得到的答案是legs_in_oyster是2。

如果您单独定义Oyster - 即在LEGS = 2超出范围之后定义它,则会得到4的响应。

这表明嵌套类的行为与名称空间不同,也许更像是一个闭包。

- -编辑 - -

irb(main):076:0> class MyAnimals::RunningRoach < Animal; def using_legs; LEGS; end; end
=> nil
irb(main):077:0> MyAnimals::RunningRoach.new.kind_of?(MyAnimals)
=> false
irb(main):078:0> MyAnimals::RunningRoach.new.kind_of?(Animal)
=> true
irb(main):081:0> class MyAnimals::Mantis < MyAnimals; def killing_legs; LEGS; end; end
=> nil
irb(main):082:0> MyAnimals::Mantis.new.kind_of?(Animal)
=> false
irb(main):083:0> MyAnimals::Mantis.new.kind_of?(MyAnimals)
=> true
irb(main):084:0> MyAnimals::Mantis.new.killing_legs
=> 2
irb(main):085:0> MyAnimals::RunningRoach.new.using_legs
=> 4

根据“Ruby编程语言”,常量在首先使用的地方的词法作用域中查找,而在继承层次结构中查找常量。那么继承动物的东西的词汇范围是什么?动物本身,对吧?MyAnimals类重新定义LEGS,因此任何使用LEGS并在 MyAnimals中定义的内容都将首先在MyAnimal中查找LEGS。

扫码关注云+社区