给出以下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)
第二,是否在任何地方声明一个常量,将它与它所声明的类的范围联系起来?为什么?
首先,执行以下代码时会发生什么:
Run Code Online (Sandbox Code Playgroud)PARENTS = [ FATHER = :father, MOTHER = :mother ]
PARENTS = ...尝试设置常量PARENTS.但为了做到这一点,它必须评估任务的右侧:
[...]尝试创建一个数组.但为了做到这一点,它必须评估其论点:
FATHER = :father将常量设置FATHER为:father.这个赋值的结果是:father第一个参数.MOTHER = :mother将常量设置MOTHER为:mother.这个赋值的结果是:mother第二个参数.所以按时间顺序:
FATHER设置为:fatherMOTHER设置为:mother:father和:mother创建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)
以上仅用于演示目的,没有必要实际执行此操作.