为什么常量在数组中声明,并分配给其他常量,可以作为Ruby中的类常量访问?

Ami*_*ani 2 ruby constants

给出以下Ruby类

class Example
  PARENTS = [
    FATHER = :father,
    MOTHER = :mother
  ]
end
Run Code Online (Sandbox Code Playgroud)

这些按预期工作

> Example::PARENTS
#=> [:father, :mother]
> Example::PARENTS[0]
#=> :father
> Example::PARENTS[1]
#=> :mother
Run Code Online (Sandbox Code Playgroud)

但是,为什么这样做呢?

> Example::FATHER
#=> :father
> Example::MOTHER
#=> :mother
Run Code Online (Sandbox Code Playgroud)

实际上,为什么Example类的范围中有三个常量?

> Example.constants
#=> [:MOTHER, :PARENTS, :FATHER]
Run Code Online (Sandbox Code Playgroud)

至关重要的是,如果我使用其他方法扩展该类:

class Example
  def self.whos_your_daddy
    FATHER
  end
end
Run Code Online (Sandbox Code Playgroud)

它正常访问常量.

> Example.whos_your_daddy
#=> :father
Run Code Online (Sandbox Code Playgroud)

这种行为怎么可能?通过声明常量内部数组的,我希望他们能够在阵列内的作用域.请在您的答案中引用相关文档.

编辑:我想我会澄清,回答这个问题的最简单方法是解释两件事:

首先,执行以下代码时会发生什么:

PARENTS = [
  FATHER = :father,
  MOTHER = :mother
]
Run Code Online (Sandbox Code Playgroud)

第二,是否在任何地方声明一个常量,将它与它所声明的类的范围联系起来?为什么?

Ste*_*fan 5

首先,执行以下代码时会发生什么:

PARENTS = [
  FATHER = :father,
  MOTHER = :mother
]
Run Code Online (Sandbox Code Playgroud)
  • PARENTS = ...尝试设置常量PARENTS.但为了做到这一点,它必须评估任务的右侧:
    • [...]尝试创建一个数组.但为了做到这一点,它必须评估其论点:
      • FATHER = :father将常量设置FATHER:father.这个赋值的结果是:father第一个参数.
      • MOTHER = :mother将常量设置MOTHER:mother.这个赋值的结果是:mother第二个参数.

所以按时间顺序:

  1. 常量FATHER设置为:father
  2. 常量MOTHER设置为:mother
  3. 与元件的阵列:father:mother创建
  4. 常量PARENTS设置为该数组

您的代码相当于:

FATHER = :father
MOTHER = :mother
PARENTS = [FATHER, MOTHER]  # or [:father, :mother]
Run Code Online (Sandbox Code Playgroud)

通过在数组中声明常量,我希望它们在数组中作用域.请在您的答案中引用相关文档.

您可以使用它Module.nesting来确定当前嵌套,即将在以下位置定义常量:( 文档中的更多示例)

class Example
  p outer_nesting: Module.nesting
  PARENTS = [
    p(inner_nesting: Module.nesting)
  ]
end
Run Code Online (Sandbox Code Playgroud)

输出:

{:outer_nesting=>[Example]}
{:inner_nesting=>[Example]}
Run Code Online (Sandbox Code Playgroud)

如您所见,数组文字不会影响当前嵌套.两个地点的常数将在下面定义Example.

如果你真的想在数组内"声明"常量(即在数组的单例类中),你可以这样做:

class Example
  PARENTS = []
  class << PARENTS
    FATHER = :father
    MOTHER = :mother
    PARENTS.push(FATHER, MOTHER)
  end
end

p Example.constants                          #=> [:PARENTS]
p Example::PARENTS.singleton_class.constants #=> [:FATHER, :MOTHER]
Run Code Online (Sandbox Code Playgroud)

以上仅用于演示目的,没有必要实际执行此操作.