我们可以很容易地从许多著名的存储库中找到这种风格,如rack,rails等。
For example in rack:
PATH_INFO = 'PATH_INFO'.freeze
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
SCRIPT_NAME = 'SCRIPT_NAME'.freeze
QUERY_STRING = 'QUERY_STRING'.freeze
CACHE_CONTROL = 'Cache-Control'.freeze
CONTENT_LENGTH = 'Content-Length'.freeze
CONTENT_TYPE = 'Content-Type'.freeze
HTTP_IF_MODIFIED_SINCE = 'HTTP_IF_MODIFIED_SINCE'.freeze
HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze
HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze
我想知道为什么这些恒定的弦被冻结了。因为它们都是常量,所以应该只有一个示例。当然,我们可以把"foo".freeze
放在某个地方来引用同一个单例示例,但是人们通常会写像HTTP_IF_MODIFIED_SINCE
这样的字面变量名。
所以在我看来,尽管使用#freeze
,它也没有任何区别,那么为什么人们要冻结常数呢?
3条答案
按热度按时间oxiaedzo1#
当你给一个已经初始化的常量重新赋值时,Ruby会打印一个警告,这是正确的:
但是对于改变常数的值的部分没有保护。没有
freeze
的示例:但是
freeze
允许保护常量的值不被更改。例如freeze
:xoshrz7s2#
通常Rubyist冻结字符串字面量以使执行更快。如果在某个控制器中有一些函数调用,例如下面的函数,每个请求都会调用该函数。
Ruby每次都会定义一个新的垃圾字符串对象。对象分配不是自由的。它消耗内存和CPU。垃圾将在那里,直到GC收集它们。
但如果文字被冻结
ruby分配一次并缓存它以备后用。此外,字符串对象将是不可变的,在多线程环境中使用是安全的。
根据Matz的说法,从ruby 3.0开始,ruby将冻结所有字符串。
更新:
如果你在ruby文件的开头加上下面的注解,那么整个文件中的每个字符串都是不可变的。当你试图为多线程环境优化你的应用程序时,这是非常有帮助的。
或者你甚至可以用
--enable-frozen-string-literal
开关启动你的Ruby进程。isr3a4wc3#
为什么在流行的项目中会看到这种常数的持续冻结,一个解释是它们使用了Rubocop,一种代码分析器。
这是一个标准的Rubocop rule,常量不应该是可变的,因为@spickermann上面提到的原因。