Ruby:对类定义的显式范围

免责声明:代码取自ruby公案

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

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结果为2,我理解为什么 – 在inheritanceheirarchy之前搜索常量的词法空间。

然后定义这个类:

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

该教程说,现在调用MyAnimals::Oyster.new.legs_in_oyster结果为4,我无法弄明白。 在我看来,Oyster是MyAnimals中的嵌套类,因此我希望它的行为与Birds类在上面的行为相同。 我遗漏了一些关于用明确的范围界定声明类Oyster的关键信息。

任何人都可以向我解释这个吗? 我通过谷歌发现了数百个ruby课程教程,但没有一个能解决这个问题。

先感谢您…

我认为这个例子最好地解释了它。 Ruby按此顺序搜索常量定义:

  1. 封闭范围
  2. 任何外部范围(重复到达顶级)任何外部范围(最多但不包括顶级
  3. 包含的模块
  4. 超(ES)
  5. 顶层
  6. 宾语
  7. 核心

编辑

感谢Mark Amery指出这个错误。 只有在没有封闭范围和/或超类的情况下才能达到顶级。 链接的例子实际上使这个清楚,遗憾的是我读错了。

这种情况的一个例子:

 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 

如果你定义Oyster INSIDE MyAnimals类定义,那么你得到leg_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编程语言”,常量在首先使用它们的地方的词法范围中查找,然后在inheritance层次结构中查找。 那么inheritanceAnimal的词汇范围是什么? 动物本身吧? MyAnimals类重新定义LEGS,因此任何使用LEGS并 MyAnimals中定义的东西都将首先在MyAnimals中查找LEGS。