找到篇好文,闲来无事翻译成中文,分享给大伙。欢迎随时讨论~~ 原文链接:http://blog.honeybadger.io/when-to-use-freeze-and-frozen-in-ruby/
如今我们经常看到 freeze 应用在 Ruby 代码中。但对于为什么要用 freeze(冻结)往往不完全清楚。在这遍文章中,我们将了解开发人员会采取冻结变量的几种最常见理由。为了清楚的描述各种情况,我从 Rails 代码库和其他主流的开 源 项 目中摘录了代码来举例。
创建不变的常量
在 Ruby 语言中,常量是可变的。这有点让人困惑,但从代码中能轻易的理解到这一点。下面,我创建一组字符常量,并且同时添加另一组字符上去。
通过运用 freeze,我可以创建一个真正意义上的常量。这回,当我尝试修改字符,得到的结果是 RuntimeError。
这是一个在 ActionDispatch 代码库上真实的例子。Rails 用文本“[FILTERED]”来替换在日志中敏感数据而达到隐藏数据的效果。这个文本正是储存在冻结常量中。
减少对象分配
给你的 Ruby app 加速的最佳方法之一是减少已创建对象的数量。关于对象分配一个让人头疼的原因来自散落在大多数应用中到处都是的字符串。 每次你调用一函数,例如是 log(“foobar”),你就要新建一个字符串对象。如果你的代码每秒要调用上千次函数,这就意味着你每秒要创建上千个字符串。这样工作量就很大了。 幸运的是,Ruby 给了我们一种优化的方式。如果我们冻结一个字符串常量,那么 Ruby 的解析器就只会创建一个字符串对象,并且会储存起来备将来使用。这这里,我将 frozen 和 non-frozen 的字符串进行了性能对比,结果显示性能提升了 50%。
你可以通过 Rail router 来看到运行过程。Router 用于响应每个网页的要求,必须要运行的很快,这就需要许多 frozen 的字符串常量。
Ruby2.2 和之后版本的软件内置优化
Ruby 2.2 及后续版本(MRI)会自动冻结含有散列键的字符串常量。
而且根据 Matz 公布的消息,在 Ruby3 的所有字符串常量将会被自动冻结。
对象的取值和函数式编程
尽管 Ruby 不是一种函数式编程语言,但是许多使用者都开始注意到里面函数样式的价值。这种样式的一个主要宗旨是,要防止外部修改。对象初始化之后不应发生改变。 通过在构造器里调用 freeze 函数,保证了对象不会更改。任何意外的外部修改都会导致异常值的出现。