Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么常量在数组中声明,并分配给其他常量,在Ruby中可以作为类常量访问?_Ruby_Constants - Fatal编程技术网

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

为什么常量在数组中声明,并分配给其他常量,在Ruby中可以作为类常量访问?,ruby,constants,Ruby,Constants,给定以下Ruby类 class Example PARENTS = [ FATHER = :father, MOTHER = :mother ] end 这些工作如期进行 > Example::PARENTS #=> [:father, :mother] > Example::PARENTS[0] #=> :father > Example::PARENTS[1] #=> :mother > Example.instance_

给定以下Ruby类

class Example
  PARENTS = [
    FATHER = :father,
    MOTHER = :mother
  ]
end
这些工作如期进行

> Example::PARENTS
#=> [:father, :mother]
> Example::PARENTS[0]
#=> :father
> Example::PARENTS[1]
#=> :mother
> Example.instance_variable_get :@parents
#=> [:father, :mother]
> Example.instance_variable_get(:@parents)[0]
#=> :father
> Example.instance_variable_get(:@parents)[1]
#=> :mother
然而,为什么这样做有效

> Example::FATHER
#=> :father
> Example::MOTHER
#=> :mother
事实上,为什么示例类的作用域中有三个常量

> Example.constants
#=> [:MOTHER, :PARENTS, :FATHER]
关键是,如果我用一个额外的方法扩展类:

class Example
  def self.whos_your_daddy
    FATHER
  end
end
class Example
  def self.whos_your_daddy
    @father
  end
end
它像正常情况一样访问常量

> Example.whos_your_daddy
#=> :father
> Example.whos_your_daddy
#=> :father
这种行为怎么可能?通过在数组中声明常量,我希望它们的作用域在数组中。请在回答中引用相关文件

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

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

PARENTS = [
  FATHER = :father,
  MOTHER = :mother
]
PARENTS = [
  FATHER = :father,
  MOTHER = :mother
]

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

我可以理解它是如何令人困惑的,但除了不鼓励将值重新分配给常量之外,在范围方面,实例变量和常量非常相似

第一个类声明中的可视技巧是在数组中声明常量

第一:理解当您声明一个常量时,返回的值就是您的定义。例如

FATHER = :father
#=> :father
现在,让我们看看常量声明:

PARENTS = [
  FATHER = :father,
  MOTHER = :mother
]
要声明父级,您可以使用:

PARENTS = [
  :father,
  :mother
]
但您更进一步,在定义中声明了一个常量。现在请理解实例变量和常量的范围是相似的,它与在其中声明的实例相关联,因此在任何地方声明常量都会将其与实例相关联。

通过执行
FATHER=:FATHER
,您已经声明了另一个常量,并且常量的范围始终是它在其中声明的类,在本例中是
示例
。这同样适用于
MOTHER=:MOTHER

如果您更习惯于实例变量,这与此工作的原因相同:给定以下Ruby类

class Example
  @parents = [
    @father = :father,
    @mother = :mother
  ]
end
这些工作如期进行

> Example::PARENTS
#=> [:father, :mother]
> Example::PARENTS[0]
#=> :father
> Example::PARENTS[1]
#=> :mother
> Example.instance_variable_get :@parents
#=> [:father, :mother]
> Example.instance_variable_get(:@parents)[0]
#=> :father
> Example.instance_variable_get(:@parents)[1]
#=> :mother
但这也行得通

> Example.instance_variable_get :@father
#=> :father
> Example.instance_variable_get :@mother
#=> :mother
事实上,这三个都在示例类的范围内

> Example.instance_variables
#=> [:@mother, :@parents, :@father]
关键是,如果我用一个额外的方法扩展类:

class Example
  def self.whos_your_daddy
    FATHER
  end
end
class Example
  def self.whos_your_daddy
    @father
  end
end
它像平常一样访问实例变量

> Example.whos_your_daddy
#=> :father
> Example.whos_your_daddy
#=> :father

你的答案就在你的问题里

class Example
  PARENTS = [
    FATHER = :father,
    MOTHER = :mother
  ]
end
这里有3个常量(
父母
父亲
母亲
)。它们在一个范围内。数组不生成新作用域

Example.constants
方法只显示它们

即使将方法添加到类中,也不会改变任何内容

class Example
  PARENTS = [
    FATHER = :father,
    MOTHER = :mother
  ]

  def self.whos_your_daddy
    FATHER
  end
end

Example.constants #=> [:MOTHER, :PARENTS, :FATHER]

我在红宝石里找到了这个​​编程手册,第94页:

在类或模块中定义的常量可以在类或模块中的任何位置不加修饰地访问。在类或模块之外,可以使用作用域运算符(前缀为返回相应类或模块对象的表达式)访问它们。在任何类或模块之外定义的常量可以不加修饰地访问,也可以使用不带前缀的范围运算符访问。方法中不能定义常量。可以通过在常量名称之前使用类或模块名称和范围运算符,从外部将常量添加到现有类和模块中

结论:一个类中不能有两个同名的常量,一个在数组内部,一个在数组外部。因此您不需要作用域来访问它,因为作用域是整个类


在常量数组中不需要常量,因为数组是常量,它的内部值是常量​​数组定义不是一个块。它不在数组的作用域中运行

这与:

PARENTS = []
PARENTS << mom = :mother
赋值返回指定的值:

> foo = "bar"
"bar"
> puts foo
bar
> puts(foo = "baz")
baz
> puts foo
baz

不能在数组中“存储”类似于
MOTHER=:MOTHER
的内容,因为它不是一个值,它返回一个值,即
:MOTHER

一个简短的答案可能是:

  • 常量只能存储在*中。定义为,而不是
  • 是的
  • 阵列实例不是模块
您的代码相当于:

class Example
  PARENTS = [
    Example.const_set("FATHER", :father),
    Example.const_set("MOTHER", :mother)
  ] 
end
FATHER = :father
MOTHER = :mother
PARENTS = [FATHER, MOTHER]  # or [:father, :mother]
通过一些测试:

puts Example.is_a? Module
# true
puts Example.is_a? Class
# true
p Example::PARENTS
# [:father, :mother]
p Example.constants
# [:FATHER, :MOTHER, :PARENTS]
puts Example::PARENTS.is_a? Module
# false
Example::PARENTS.const_set("UNCLE", :uncle)
# undefined method `const_set' for [:father, :mother]:Array (NoMethodError)
*:顶级常量(=在类或模块外部定义的常量)似乎存储在
对象中

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

PARENTS = [
  FATHER = :father,
  MOTHER = :mother
]
PARENTS = [
  FATHER = :father,
  MOTHER = :mother
]
  • PARENTS=…
    尝试设置常量
    PARENTS
    。但为了做到这一点,它必须评估任务的右侧:
    • […]
      尝试创建数组。但为了做到这一点,它必须评估其论点:
      • FATHER=:FATHER
        将常量
        FATHER
        设置为
        :FATHER
        。此赋值的结果是
        :父
        ,它成为第一个参数
      • MOTHER=:MOTHER
        将常量
        MOTHER
        设置为
        :MOTHER
        。这个赋值的结果是
        :mother
        ,它成为第二个参数
所以按时间顺序:

  • 常量
    父亲
    设置为
    :父亲
  • 常量
    MOTHER
    设置为
    :MOTHER
  • 创建了一个包含元素
    :父
    :母
    的数组
  • 常量
    父项
    设置为该数组
  • 您的代码相当于:

    class Example
      PARENTS = [
        Example.const_set("FATHER", :father),
        Example.const_set("MOTHER", :mother)
      ] 
    end
    
    FATHER = :father
    MOTHER = :mother
    PARENTS = [FATHER, MOTHER]  # or [:father, :mother]
    
    通过在数组中声明常量,我希望它们的作用域在数组中。请在回答中引用相关文件

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

    输出:

    {:outer_nesting=>[Example]}
    {:inner_nesting=>[Example]}
    
    如您所见,数组文本不会影响当前嵌套。两个位置的常数将在
    示例下定义

    如果你真的想申报