加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

如何解冻Ruby中的对象?

发布时间:2020-12-16 20:02:57 所属栏目:百科 来源:网络整理
导读:在 Ruby中有 Object#freeze ,可以防止对对象的进一步修改: class Kingdom attr_accessor :weather_conditionsendarendelle = Kingdom.newarendelle.frozen? # = falsearendelle.weather_conditions = 'in deep,deep,deep snow'arendelle.freezearendelle.fr
在 Ruby中有 Object#freeze,可以防止对对象的进一步修改:
class Kingdom
  attr_accessor :weather_conditions
end

arendelle = Kingdom.new
arendelle.frozen? # => false
arendelle.weather_conditions = 'in deep,deep,deep snow'
arendelle.freeze
arendelle.frozen? # => true
arendelle.weather_conditions = 'sun is shining'
  # !> RuntimeError: can't modify frozen Kingdom

script = 'Do you want to build a snowman?'.freeze
script[/snowman/] = 'castle of ice'
  # !> RuntimeError: can't modify frozen String

但是,没有对象#解冻.有没有办法解冻冻结的王国?

解决方法

是和否没有任何使用标准API的直接方式.但是,有一些了解什么#freeze?是的,你可以解决它.注意:这里的一切都是MRI当前版本的实现细节,可能会有所变化.

CRuby中的对象存储在struct RVALUE中.
方便的是,结构中的第一件事是VALUE标志.
所有对象#freeze都设置了一个标志,称为FL_FREEZE,实际上是equal to RUBY_FL_FREEZE.RUBY_FL_FREEZE基本上是标志中的11th bit.
所有你要解冻的对象都要取消设置第11位.

为此,您可以使用Fiddle,它是标准库的一部分,可让您修改C级语言:

require 'fiddle'

class Object
  def unfreeze
    Fiddle::Pointer.new(object_id * 2)[1] &= ~(1 << 3)
  end
end

非immediate value objects in Ruby存储在address =他们的object_id * 2上.请注意,重要的是进行区分,以便您知道这不会让您解冻Fixnums.

由于我们要改变第11位,所以我们必须使用第二个字节的第3位.因此,我们使用[1]访问第二个字节.

?(1 <3)移动3个位置,然后使结果反转.这样,掩码中零位的唯一位将是第三个,所有其他将是一个. 最后,我们只用位和(& =)应用掩码.

foo = 'A frozen string'.freeze
foo.frozen? # => true
foo.unfreeze
foo.frozen? # => false
foo[/ (?=frozen)/] = 'n un'
foo # => 'An unfrozen string'

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读