0

我无法管理哈希子类Marshal.loadMarshal.dumped 实例:

class MarshalDumpableHash < Hash

  def initialize(constructor = {})
    if constructor.is_a?(Hash)
      super()
      update(constructor)
    else
      super(constructor)
    end
  end

  def marshal_dump
    p self
    self
  end

  def marshal_load(hash)
    p hash
    update(hash)
  end

end


h = { asd: 'ciao' }

p MarshalDumpableHash.new(h) #=> {:asd=>"ciao"}
p Marshal.dump(MarshalDumpableHash.new(h)) #=> "\x04\bU:\x18MarshalDumpableHash@\x00"

p Marshal.load(Marshal.dump(MarshalDumpableHash.new(h))) #=> {} WHY?

方法内部打印,而方法p self内部打印的对我来说听起来很奇怪marshal_dump{:asd=>"ciao"}marshal_load{}

4

1 回答 1

2

marshal_dump返回的方法self不是使用marshal_dumpand的用例marshal_load,因为内置的转储和加载可以做到这一点。所以如果你只是想编组self,你不必编写任何自定义marshal_dumpmarshal_load

class Subclassed < Hash
end

s = Subclassed.new
s[:foo] = :bar
Marshal.load(Marshal.dump(s)).class #=> Subclassed

这些方法适用于当您在加载转储对象时确实有关于不想重新加载的对象的多余信息的用例。这是为了节省空间。例如:

class Subclassed < Hash

  attr_reader :surplus_info

  def initialize(surplus_info)
    @surplus_info = surplus_info
  end

  def marshal_dump
    Hash.new.merge(self)
  end

  def marshal_load other
    update(other)
  end
end

如果没有marshal_dumpmarshal_load,则生成的编组字符串将是:

"\004\bIC:\017Subclassed{\006:\bfoo:\bbar\006:\022@surplus_info\"\bfoo"

其中有多余的信息。使用编组加载和转储,您将能够减少编组字符串:

"\004\bIU:\017Subclassed{\006:\bfoo:\bbar\000" 

这就是这些方法的目的。此外,红宝石文档指出:

marshal_dump 可能会导致更小的 Marshal 字符串。

此外,该文档对使用有点模糊marshal_dump

转储对象时,将调用 marshal_dump 方法。marshal_dump 必须返回包含 marshal_load 重构对象所需信息的结果。结果可以是任何对象。

它可能应该是“结果可以是除self”之外的任何对象。我不知道红宝石在返回时显示的行为self是否marshal_dump真的是故意的(至少一个错误会很好),或者它是否只是被遗忘了,因为它不是真正的用例。

于 2013-02-22T17:32:33.307 回答