Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.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 为什么在Class.new代码块中直接赋值常量不起作用_Ruby_Constants - Fatal编程技术网

Ruby 为什么在Class.new代码块中直接赋值常量不起作用

Ruby 为什么在Class.new代码块中直接赋值常量不起作用,ruby,constants,Ruby,Constants,考虑以下代码: c1 = Class.new { ANSWER = 42 } #⇒ #<Class:0x00556c8fc09c60> < Object c1.constants #⇒ [] c1.new.class.constants #⇒ [] c1.new.singleton_class.constants #⇒ [] Object.constants.grep /ANS/ #⇒ [:ANSWER] 我的问题是:是什么阻止了在类上正确分配常量。第一个代码片段中的新实例?

考虑以下代码:

c1 = Class.new { ANSWER = 42 }
#⇒ #<Class:0x00556c8fc09c60> < Object
c1.constants
#⇒ []
c1.new.class.constants
#⇒ []
c1.new.singleton_class.constants
#⇒ []
Object.constants.grep /ANS/
#⇒ [:ANSWER]
我的问题是:是什么阻止了在
类上正确分配常量。第一个代码片段中的新
实例?

文档的状态是,“如果给定了一个块,它将传递给类对象,并且该块将在该类的上下文中进行评估,如
Class\u eval
”,这意味着

c = Class.new { ANSWER = 42 }
相当于

c = Class.new
c.class_eval  { ANSWER = 42 }
class\u eval
在顶级创建常量,因为它是在顶级的
c
上调用的
c.class_eval{ANSWER=42}
实际上与

ANSWER = 42
它在
对象上创建一个常量

Object::ANSWER
  #=> 43
这里是另一条路

NUMBER = 43
Object::NUMBER
  #=> 43

c = Class.new
c.const_set(:NUMBER, 48)
c::NUMBER
  #=> 48
c.class_eval { puts NUMBER }
43
这是另一个例子

class F
  class G; end
  G.class_eval { HIPPO = 5 }
end

F::HIPPO
  #=> 5
F::G::HIPPO
  #=> #NameError (uninitialized constant F::G::HIPPO)
  #   Did you mean?  F::HIPPO
但是,

class F
  class G
    class_eval { HIPPO = 5 }
  end
end

F::HIPPO
  #=> NameError (uninitialized constant F::HIPPO)
F::G::HIPPO
  #=> 5
读者:请参阅和了解使用
class\u eval
(创建常量的补充)进行常量查找。(搜索
“class_eval”
)。

文档中的状态是,“如果给定了一个块,它将传递给类对象,并且该块将在该类的上下文中进行评估,如
class_eval
”,这意味着

c = Class.new { ANSWER = 42 }
相当于

c = Class.new
c.class_eval  { ANSWER = 42 }
class\u eval
在顶级创建常量,因为它是在顶级的
c
上调用的
c.class_eval{ANSWER=42}
实际上与

ANSWER = 42
它在
对象上创建一个常量

Object::ANSWER
  #=> 43
这里是另一条路

NUMBER = 43
Object::NUMBER
  #=> 43

c = Class.new
c.const_set(:NUMBER, 48)
c::NUMBER
  #=> 48
c.class_eval { puts NUMBER }
43
这是另一个例子

class F
  class G; end
  G.class_eval { HIPPO = 5 }
end

F::HIPPO
  #=> 5
F::G::HIPPO
  #=> #NameError (uninitialized constant F::G::HIPPO)
  #   Did you mean?  F::HIPPO
但是,

class F
  class G
    class_eval { HIPPO = 5 }
  end
end

F::HIPPO
  #=> NameError (uninitialized constant F::HIPPO)
F::G::HIPPO
  #=> 5
读者:请参阅和了解使用
class\u eval
(创建常量的补充)进行常量查找。(搜索
“等级评估”
)。

  • self
    (无接收者消息发送的上下文和实例变量)
  • 默认定义对象(没有明确目标的
    def
    方法定义表达式的上下文,即
    def bar
    而不是
    def foo.bar
  • 默认常量定义点
不幸的是,虽然我链接到上面的文章列出了这三个变量,但它只讨论了前两个变量,并将默认常量定义点推迟到了后来的一篇文章中,这篇文章从未撰写过

无论如何,记住这三种情况是很重要的,并且要知道它们何时改变,何时不改变

特别是,一个块只改变词法上下文,而不改变其他内容。块不会更改自身,不会更改默认定义对象,也不会更改默认常量定义点

然而,有些方法的明确目的是改变这三种上下文中的一种或多种

*\u eval
方法系列会更改
self
(上下文1)和默认的定义对象(上下文2),但不会更改默认的常量定义点(上下文3)。特别是,所有
*\u eval
*\u exec
)方法都将
self
设置到接收器。
实例*
版本将默认定义对象设置为接收方的单例类,
模块*
类*
版本将默认定义对象设置为接收方

但是,默认的常量定义点没有更改,因此常量定义(和查找)的工作原理与以前一样:定义转到最近的词汇性封闭模块定义,查找从最近的词汇性封闭模块定义开始,并通过继承以词汇性向外和动态向上进行

据我所知,唯一改变默认常量定义点的构造是
模块
/
定义。

:

  • self
    (无接收者消息发送的上下文和实例变量)
  • 默认定义对象(没有明确目标的
    def
    方法定义表达式的上下文,即
    def bar
    而不是
    def foo.bar
  • 默认的常量定义点
不幸的是,虽然我链接到上面的文章列出了这三个变量,但它只讨论了前两个变量,并将默认常量定义点推迟到了后来的一篇文章中,这篇文章从未撰写过

无论如何,记住这三种情况是很重要的,并且要知道它们何时改变,何时不改变

特别是,一个块只改变词法上下文,而不改变其他内容。块不会更改自身,不会更改默认定义对象,也不会更改默认常量定义点

然而,有些方法的明确目的是改变这三种上下文中的一种或多种

*\u eval
方法系列会更改
self
(上下文1)和默认的定义对象(上下文2),但不会更改默认的常量定义点(上下文3)。特别是,所有
*\u eval
*\u exec
)方法都将
self
设置到接收器。“code”>“instance”
versions将默认定义设置为接收器的singleton类、“code”>“module”
class_*
版本将默认定义设置为接收器

但是,默认的常量定义点没有更改,因此常量定义(和查找)的工作原理与以前一样:定义转到最近的词汇性封闭模块定义,查找从最近的词汇性封闭模块定义开始,并通过继承以词汇性向外和动态向上进行


据我所知,唯一改变默认常量定义点的结构是
模块
/
定义。

类似:@MarcinKołodziej似乎揭示了这个问题,词法范围在这里很重要。我们似乎需要一个显式的
关键字来打开新的作用域。这真的很疯狂,但想当然地认为
定义方法
也能起到类似的作用